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.

6481 lines
204 KiB

  1. //++
  2. //
  3. // Module Name:
  4. // trap.s
  5. //
  6. // Abstract:
  7. // Low level interruption handlers
  8. //
  9. // Author:
  10. // Bernard Lint 12-Jun-1995
  11. //
  12. // Environment:
  13. // Kernel mode only
  14. //
  15. // Revision History:
  16. //
  17. //
  18. // Open Design Issues:
  19. //
  20. //--
  21. #if DBG // interruption logging is enabled in checked and free builds
  22. #define INTERRUPTION_LOGGING 1
  23. #endif // DBG
  24. #include "ksia64.h"
  25. .file "trap.s"
  26. .explicit
  27. //
  28. // Globals imported:
  29. //
  30. PublicFunction(KeBugCheckEx)
  31. PublicFunction(KiApcInterrupt)
  32. PublicFunction(KiCheckForSoftwareInterrupt)
  33. PublicFunction(KiDispatchException)
  34. PublicFunction(KiExternalInterruptHandler)
  35. PublicFunction(KiFloatTrap)
  36. PublicFunction(KiFloatFault)
  37. PublicFunction(KiGeneralExceptions)
  38. PublicFunction(KiUnimplementedAddressTrap)
  39. PublicFunction(KiNatExceptions)
  40. PublicFunction(KiMemoryFault)
  41. PublicFunction(KiOtherBreakException)
  42. PublicFunction(KiPanicHandler)
  43. PublicFunction(KiSingleStep)
  44. PublicFunction(KiUnalignedFault)
  45. PublicFunction(PsConvertToGuiThread)
  46. PublicFunction(ExpInterlockedPopEntrySListFault)
  47. PublicFunction(KiDebugFault)
  48. PublicFunction(KeSetLowPsrBit)
  49. PublicFunction(KiIA32ExceptionVectorHandler)
  50. PublicFunction(KiIA32InterruptionVectorHandler)
  51. PublicFunction(KiIA32InterceptionVectorHandler)
  52. .global KiSystemServiceHandler
  53. .global KeServiceDescriptorTableShadow
  54. .global KeGdiFlushUserBatch
  55. .global KdDebuggerEnabled
  56. .global MiDefaultPpe
  57. .global MiNatPte
  58. .global KiIA64RseNumOfMaxDirty
  59. #include "icecap.h"
  60. #ifdef _CAPKERN
  61. PublicFunction(_CAP_ThreadID)
  62. PublicFunction(_CAP_SetCPU)
  63. #endif
  64. // For Conditional Interrupt Logging
  65. #define UserSystemcallBit 61
  66. #define ExternalInterruptBit 62
  67. .global KiVectorLogMask
  68. //
  69. // Register aliases used throughout the entire module
  70. //
  71. //
  72. // Banked general registers
  73. //
  74. // h16-h23 can only be used when psr.ic=1.
  75. //
  76. // h24-h31 can only be used when psr.ic=0 (these are reserved for tlb
  77. // and pal/machine check handlers when psr.ic=1).
  78. //
  79. //
  80. // Shown below are aliases of bank 0 registers used in the low level handlers
  81. // by macros ALLOCATE_TRAP_FRAME, SAVE_INTERRUPTION_RESOURCES, and
  82. // RETURN_FROM_INTERRUPTION. When the code in the macros are changes, these
  83. // register aliases must be reviewed.
  84. //
  85. rHIPSR = h16
  86. rHpT2 = h16
  87. rHIIPA = h17
  88. rHRSC = h17
  89. rHDfhPFS = h17 // used to preserve pfs in KiDisabledFpRegisterVector
  90. rHIIP = h18
  91. rHFPSR = h18
  92. rHRNAT2 = h18
  93. rHOldPreds = h19
  94. rHBrp = h19
  95. rHInitBStore= h19
  96. rHIFS = h20
  97. rHPFS = h20
  98. rHBSP = h20
  99. rHISR = h21
  100. rHUNAT = h21
  101. rHBSPSTORE = h21
  102. rHpT3 = h21
  103. rHSp = h22
  104. rHDfhBrp = h22 // used to preserve brp in KiDisabledFpRegisterVector
  105. rHRNAT = h22
  106. rHpT4 = h22
  107. rHpT1 = h23
  108. rTH3 = h24
  109. rHHandler = h25
  110. rTH1 = h26
  111. rTH2 = h27
  112. rHIIM = h28
  113. rHIFA = h28
  114. rHEPCVa = h29
  115. rHVector = h29
  116. rHEPCVa2 = h30
  117. rPanicCode = h30
  118. rTH4 = h31
  119. //
  120. // General registers used through out module
  121. //
  122. pApc = ps0 // User Apc Pending
  123. pUser = ps1 // mode on entry was user
  124. pKrnl = ps2 // mode on entry was kernel
  125. pUstk = ps3
  126. pKstk = ps4
  127. pEM = ps5 // EM ISA on kernel entry
  128. pIA = ps6 // X86 ISA on kernel entry
  129. pKDbg = ps7 // Kernel debug Active
  130. pUDbg = ps8 // Kernel debug Active
  131. //
  132. // Kernel registers used through out module
  133. //
  134. rkHandler = k6 // specific exception handler
  135. //
  136. // Macro definitions for this module only
  137. //
  138. //
  139. // Define vector/exception entry/exit macros.
  140. // N.B. All HANDLER_ENTRY functions go into .nsc section with
  141. // KiNormalSystemCall being the first.
  142. //
  143. #define HANDLER_ENTRY(Name) \
  144. .##global Name; \
  145. .##proc Name; \
  146. Name::
  147. #define HANDLER_ENTRY_EX(Name, Handler) \
  148. .##global Name; \
  149. .##proc Name; \
  150. .##type Handler, @function; \
  151. .##personality Handler; \
  152. Name::
  153. #define VECTOR_ENTRY(Offset, Name, Extra0) \
  154. .##org Offset; \
  155. .##global Name; \
  156. .##proc Name; \
  157. Name::
  158. #define VECTOR_EXIT(Name) \
  159. .##endp Name
  160. #define HANDLER_EXIT(Name) \
  161. .##endp Name
  162. //++
  163. // Routine:
  164. //
  165. // IO_END_OF_INTERRUPT(rVector,rT1,rT2,pEOI)
  166. //
  167. // Routine Description:
  168. //
  169. // HalEOITable Entry corresponding to the vectorNo is tested.
  170. // If the entry is nonzero, then vectorNo is stored to the location
  171. // specified in the entry. If the entry is zero, return.
  172. //
  173. // Arguements:
  174. //
  175. //
  176. // Notes:
  177. //
  178. // MS preprocessor requires /* */ style comments
  179. //
  180. //--
  181. #define IO_END_OF_INTERRUPT(rVector,rT1,rT2,pEOI) ;\
  182. movl rT1 = KiPcr+PcEOITable ;\
  183. ;; ;\
  184. ld8 rT1 = [rT1] ;\
  185. ;; ;\
  186. shladd rT2 = rVector,3,rT1 ;\
  187. ;; ;\
  188. ld8 rT1 = [rT2] ;\
  189. ;; ;\
  190. cmp.ne pEOI = zero, rT1 ;\
  191. ;; ;\
  192. (pEOI) st4.rel [rT1] = rVector
  193. //++
  194. // Routine:
  195. //
  196. // VECTOR_CALL_HANDLER(Handler, SpecificHandler)
  197. //
  198. // Routine Description:
  199. //
  200. // Common code for transfer to heavyweight handlers from
  201. // interruption vectors. Put RSE in store intensive mode,
  202. // cover current frame and call handler.
  203. //
  204. // Arguments:
  205. //
  206. // Handler: First level handler for this vector
  207. // SpecificHandler: Specific handler to be called by the generic
  208. // exception handler.
  209. //
  210. // Return Value:
  211. //
  212. // None
  213. //
  214. // Notes:
  215. // Uses just the kernel banked registers (h16-h31)
  216. //
  217. // MS preprocessor requires /* */ style comments
  218. //--
  219. #define VECTOR_CALL_HANDLER(Handler,SpecificHandler) ;\
  220. mov rHIFA = cr##.##ifa ;\
  221. movl rHHandler = SpecificHandler ;\
  222. br##.##sptk Handler ;\
  223. ;;
  224. //++
  225. // Routine:
  226. //
  227. // ALLOCATE_TRAP_FRAME
  228. //
  229. // Routine Description:
  230. //
  231. // Common code for allocating trap frame on kernel entry for heavyweight
  232. // handler.
  233. //
  234. // On entry:
  235. //
  236. // On exit: sp -> trap frame; any instruction that depends on sp must be
  237. // placed in the new instruction group. Interruption resources
  238. // ipsr, iipa, iip, predicates, isr, sp, ifs are captured in
  239. // seven of the banked registers h16-23. The last one is used
  240. // by SAVE_INTERRUPTION_STATE as a pointer to save these resources
  241. // in the trap frame.
  242. //
  243. // Return Value:
  244. //
  245. // None
  246. //
  247. // Notes:
  248. // Uses just the kernel banked registers (h16-h31)
  249. //
  250. // MS preprocessor requires /* */ style comments below
  251. //--
  252. #define ALLOCATE_TRAP_FRAME ;\
  253. ;\
  254. pOverflow1 = pt2 ;\
  255. pOverflow2 = pt3 ;\
  256. pOverflow3 = pt4 ;\
  257. ;\
  258. mov rHIPSR = cr##.##ipsr ;\
  259. movl rTH1 = KiPcr+PcInitialStack ;\
  260. ;\
  261. mov rHIIP = cr##.##iip ;\
  262. mov rHOldPreds = pr ;\
  263. cover /* cover and save IFS */;\
  264. ;; ;\
  265. ;\
  266. ld8 rTH4 = [rTH1], PcBStoreLimit-PcInitialStack ;\
  267. mov rTH3 = ar##.##bsp ;\
  268. tbit##.##z pt1, pt0 = sp, 63 ;\
  269. ;; ;\
  270. ;\
  271. mov rHIIPA = cr##.##iipa ;\
  272. ld8 rTH2 = [rTH1], PcStackLimit-PcBStoreLimit ;\
  273. mov rHVector = ip /* Save this vectors address */;\
  274. ;\
  275. mov rHIFS = cr##.##ifs ;\
  276. mov rHSp = sp ;\
  277. extr##.##u rHpT1 = rHIPSR, PSR_CPL, PSR_CPL_LEN /* get mode */;\
  278. ;; ;\
  279. ;\
  280. cmp4##.##eq pKrnl, pUser = PL_KERNEL, rHpT1 /* set mode pred */;\
  281. cmp4##.##eq pKstk, pUstk = PL_KERNEL, rHpT1 /* set stack pred */;\
  282. add rHpT1 = PcKernelDebugActive-PcStackLimit, rTH1 ;\
  283. ;; ;\
  284. ;\
  285. (pKstk) ld8 rTH1 = [rTH1] ;\
  286. (pKstk) cmp##.##geu##.##unc pOverflow2 = rTH3, rTH2 ;\
  287. (pKstk) add sp = -TrapFrameLength, sp /* allocate TF */;\
  288. ;; ;\
  289. ;\
  290. ld1 rHpT1 = [rHpT1] /* load kernel db state */;\
  291. (pKstk) cmp##.##leu##.##unc pOverflow1 = sp, rTH1 ;\
  292. (pKstk) cmp##.##geu##.##unc pOverflow3 = sp, rTH3 ;\
  293. ;; ;\
  294. ;\
  295. mov rHISR = cr##.##isr ;\
  296. cmp##.##ne##.##or pKDbg = r0, rHpT1 /* kernel debug active? */;\
  297. mov rPanicCode = PANIC_STACK_SWITCH ;\
  298. ;\
  299. (pUstk) add sp = -ThreadStateSaveAreaLength-TrapFrameLength, rTH4 ;\
  300. (pOverflow1) br.spnt.few KiPanicHandler ;\
  301. (pOverflow2) br.spnt.few KiPanicHandler ;\
  302. (pOverflow3) br.spnt.few KiPanicHandler
  303. //++
  304. // Routine:
  305. //
  306. // SAVE_INTERRUPTION_STATE
  307. //
  308. // Routine Description:
  309. //
  310. // Common code for saving interruption state on entry to a heavyweight
  311. // handler.
  312. //
  313. // Arguments:
  314. //
  315. // None
  316. //
  317. // On entry:
  318. //
  319. // sp -> trap frame
  320. //
  321. // On exit:
  322. //
  323. // Static registers gp, teb, sp, fpsr spilled into the trap frame.
  324. // Registers gp, teb, fpsr are set up for kernel mode execution.
  325. //
  326. // Return Value:
  327. //
  328. // None
  329. //
  330. // Notes:
  331. //
  332. // Interruption resources already captured in bank 0 registers h16-h23.
  333. // It's safe to take data TLB fault when saving them into the trap
  334. // frame because kernel stack is always resident in memory. This macro
  335. // is carefully constructed to save the bank registers' contents in
  336. // the trap frame and reuse them to capture other register states as
  337. // soon as they are available. Until we have a virtual register
  338. // allocation scheme in place, the bank 0 register aliases defined at
  339. // the beginning of the file must be updated when this macro is modified.
  340. //
  341. // MS preprocessor requires /* */ style comments below
  342. //--
  343. #define SAVE_INTERRUPTION_STATE ;\
  344. ;\
  345. /* Save interruption resources in trap frame */ ;\
  346. ;\
  347. ;\
  348. ssm (1 << PSR_IC) | (1 << PSR_DFH) | (1 << PSR_AC) ;\
  349. add rHpT1 = TrStIPSR, sp /* -> IPSR */;\
  350. ;; ;\
  351. srlz##.##d ;\
  352. st8 [rHpT1] = rHIPSR, TrStISR-TrStIPSR /* save IPSR */;\
  353. add rHpT2 = TrPreds, sp /* -> Preds */;\
  354. ;; ;\
  355. ;\
  356. st8 [rHpT1] = rHISR, TrStIIP-TrStISR /* save ISR */;\
  357. st8 [rHpT2] = rHOldPreds, TrIntSp-TrPreds ;\
  358. ;; ;\
  359. ;\
  360. mov rHUNAT = ar##.##unat ;\
  361. st8 [rHpT1] = rHIIP, TrStIFS-TrStIIP /* save IIP */;\
  362. mov rHBrp = brp ;\
  363. ;; ;\
  364. ;\
  365. mov rHFPSR = ar##.##fpsr ;\
  366. st8 [rHpT1] = rHIFS, TrStIIPA-TrStIFS /* save IFS */;\
  367. mov rHPFS = ar##.##pfs ;\
  368. st8.spill [rHpT2] = rHSp, TrBrRp-TrIntSp /* save SP */;\
  369. ;; ;\
  370. ;\
  371. st8 [rHpT1] = rHIIPA, TrStFPSR-TrStIIPA /* save IIPA */;\
  372. st8 [rHpT2] = rHBrp, TrRsPFS-TrBrRp ;\
  373. ;; ;\
  374. ;\
  375. mov rHRSC = ar##.##rsc ;\
  376. st8 [rHpT2] = rHPFS /* save PFS */;\
  377. add rHpT2 = TrApUNAT, sp ;\
  378. ;\
  379. mov rHBSP = ar##.##bsp ;\
  380. (pUstk) movl rHInitBStore = KiPcr + PcInitialBStore ;\
  381. ;; ;\
  382. ;\
  383. mov ar##.##rsc = r0 /* put RSE in lazy mode */;\
  384. st8 [rHpT2] = rHUNAT, TrIntGp-TrApUNAT /* save UNAT */;\
  385. (pUstk) ld8 rHInitBStore = [rHInitBStore] ;\
  386. ;; ;\
  387. ;\
  388. mov rHBSPSTORE = ar##.##bspstore /* get user bspstore point */;\
  389. st8 [rHpT1] = rHFPSR, TrRsBSP-TrStFPSR /* save FPSR */;\
  390. ;; ;\
  391. ;\
  392. st8##.##spill [rHpT2] = gp, TrIntTeb-TrIntGp /* spill GP */;\
  393. st8 [rHpT1] = rHBSP, TrRsBSPSTORE - TrRsBSP /* save BSP */;\
  394. (pUstk) mov rHRNAT = ar##.##rnat /* get RNAT */;\
  395. movl rHFPSR = FPSR_FOR_KERNEL /* initial fpsr value */;\
  396. ;; ;\
  397. ;\
  398. st8 [rHpT1] = rHBSPSTORE /* save BSPSTORE */;\
  399. st8##.##spill [rHpT2] = teb, TrRsRSC-TrIntTeb /* spill TEB (r13) */;\
  400. sub rHBSP = rHBSP, rHBSPSTORE /* size of dirty region */;\
  401. (pUstk) mov teb = kteb /* sanitize teb */;\
  402. (pUstk) dep rHInitBStore = rHBSPSTORE, rHInitBStore, 0, 9 ;\
  403. ;; ;\
  404. ;\
  405. mov ar##.##fpsr = rHFPSR /* set fpsr */;\
  406. movl rHpT1 = KiPcr + PcKernelGP ;\
  407. ;\
  408. (pUstk) mov ar##.##bspstore = rHInitBStore ;\
  409. dep rHRSC = rHBSP, rHRSC, RSC_MBZ1, RSC_LOADRS_LEN ;\
  410. ;; ;\
  411. ;\
  412. (pUstk) mov ar##.##rnat = rHRNAT /* preserve the user RNAT */;\
  413. st8 [rHpT2] = rHRSC, TrRsRNAT-TrRsRSC ;\
  414. ld8 gp = [rHpT1] /* load GP */;\
  415. ;; ;\
  416. ;\
  417. /* */;\
  418. /* If previous mode is user, switch to kernel backing store */;\
  419. /* -- uses the "loadrs" approach. Note that we do not save the */;\
  420. /* BSP/BSPSTORE in the trap frame if prvious mode was kernel */;\
  421. /* */;\
  422. ;\
  423. (pUstk) mov ar##.##rsc = RSC_KERNEL /* turn rse on, kernel mode */;\
  424. (pUstk) st8 [rHpT2] = rHRNAT /* save user RNAT */;\
  425. /* adjust kernel BSPSTORE */;\
  426. /* for NAT collection */;\
  427. bsw##.##1 /* switch back to user bank */;\
  428. ;; /* stop bit required */;\
  429. //++
  430. // Routine:
  431. //
  432. // RETURN_FROM_INTERRUPTION
  433. //
  434. // Routine Description:
  435. //
  436. // Common handler code to restore trap frame and resume execution
  437. // at the interruption address.
  438. //
  439. // Arguments:
  440. //
  441. // Label
  442. //
  443. // Return Value:
  444. //
  445. // None
  446. //
  447. // Note:
  448. //
  449. // On entry: interrrupts disabled, sp -> trap frame
  450. // On exit:
  451. // MS preprocessor requires /* */ style comments below
  452. //--
  453. #define RETURN_FROM_INTERRUPTION(Label) ;\
  454. ;\
  455. .##regstk 0,5,2,0 /* must match the alloc instruction below */ ;\
  456. ;\
  457. rBSP = loc0 ;\
  458. rRnat = loc1 ;\
  459. ;\
  460. rpT1 = t1 ;\
  461. rpT2 = t2 ;\
  462. rpT3 = t3 ;\
  463. rpT4 = t4 ;\
  464. rThread = t6 ;\
  465. rApcFlag = t7 ;\
  466. rT1 = t8 ;\
  467. rT2 = t9 ;\
  468. ;\
  469. ;\
  470. alloc rT1 = 0,5,2,0 ;\
  471. movl rpT1 = KiPcr + PcCurrentThread /* ->PcCurrentThread */;\
  472. ;; ;\
  473. ;\
  474. (pUstk) ld8 rThread = [rpT1] ;\
  475. add loc4 = TrStIPSR, sp ;\
  476. (pKstk) br##.##call##.##spnt brp = KiRestoreTrapFrame ;\
  477. ;; ;\
  478. ;\
  479. ld8 loc4 = [loc4] /* load StIPSR */ ;\
  480. (pUstk) add rpT1 = ThApcState+AsUserApcPending, rThread ;\
  481. (pKstk) br##.##spnt Label##CriticalExitCode ;\
  482. ;; ;\
  483. ;\
  484. ld1 rApcFlag = [rpT1], ThAlerted-ThApcState-AsUserApcPending ;\
  485. add rBSP = TrRsBSP, sp ;\
  486. add rRnat = TrRsRNAT, sp /* -> user RNAT */;\
  487. ;; ;\
  488. ;\
  489. st1##.##nta [rpT1] = zero ;\
  490. cmp##.##ne pApc = zero, rApcFlag ;\
  491. (pUstk) tbit##.##nz.unc pUDbg = loc4, PSR_DB /* if non-zero, user debug active */;\
  492. ;; ;\
  493. ;\
  494. PSET_IRQL (pApc, APC_LEVEL) ;\
  495. movl gp = _gp /* restore to kernel gp value */;\
  496. ;\
  497. (pApc) FAST_ENABLE_INTERRUPTS ;\
  498. (pApc) mov out1 = sp ;\
  499. (pApc) br##.##call##.##sptk brp = KiApcInterrupt ;\
  500. ;; ;\
  501. ;\
  502. ld8 rBSP = [rBSP] /* user BSP */;\
  503. ld8 rRnat = [rRnat] /* user RNAT */;\
  504. ;\
  505. (pApc) FAST_DISABLE_INTERRUPTS ;\
  506. PSET_IRQL (pApc, zero) ;\
  507. (pUDbg) br##.##call##.##spnt brp = KiLoadUserDebugRegisters ;\
  508. ;; ;\
  509. ;\
  510. br##.##call##.##sptk brp = KiRestoreTrapFrame ;\
  511. ;; ;\
  512. ;\
  513. ;\
  514. Label##CriticalExitCode: ;\
  515. ;\
  516. add loc2 = TrBrRp, sp ;\
  517. add loc3 = TrRsRSC, sp ;\
  518. bsw##.##0 ;\
  519. ;; ;\
  520. ;\
  521. ld8 rHBrp = [loc2], TrRsPFS-TrBrRp ;\
  522. ld8 rHRSC = [loc3] ;\
  523. mov loc3 = RSC_KERNEL_DISABLED ;\
  524. ;; ;\
  525. ;\
  526. invala ;\
  527. (pUstk) movl out0 = KiIA64RseNumOfMaxDirty ;\
  528. ;\
  529. mov rHIPSR = loc4 ;\
  530. movl rHpT1 = KiPcr+PcHighFpOwner ;\
  531. ;; ;\
  532. ;\
  533. ld8 rHPFS = [loc2] ;\
  534. ld8 rHpT4 = [rHpT1], PcCurrentThread-PcHighFpOwner ;\
  535. extr##.##u loc2 = rHRSC, RSC_MBZ1, RSC_LOADRS_LEN ;\
  536. ;; ;\
  537. ;\
  538. (pUstk) ld8 out0 = [out0] ;\
  539. shr##.##u out1 = loc2, 3 ;\
  540. sub rHBSPSTORE = rBSP, loc2 ;\
  541. ;\
  542. ld8 loc4 = [rHpT1], PcKernelDebugActive-PcCurrentThread ;\
  543. (pUstk) mov rHRNAT2 = rRnat ;\
  544. ;; ;\
  545. ;\
  546. ld1 rHpT1 = [rHpT1] ;\
  547. dep loc3 = loc2, loc3, RSC_LOADRS, RSC_LOADRS_LEN ;\
  548. cmp##.##ne pt2 = rHpT4, loc4 ;\
  549. ;; ;\
  550. ;\
  551. mov ar##.##rsc = loc3 /* RSE off */ ;\
  552. (pUstk) cmp##.##gt pt0 = out0, out1 ;\
  553. (pt2) dep rHIPSR = 0, rHIPSR, PSR_MFH, 1 ;\
  554. (pUstk) sub loc0 = out0, out1 ;\
  555. (pKstk) br##.##spnt Label##KernelExit ;\
  556. ;; ;\
  557. ;\
  558. alloc rTH1 = 0, 0, 1, 0 ;\
  559. (pt2) dep rHIPSR = 1, rHIPSR, PSR_DFH, 1 ;\
  560. ;; ;\
  561. (pt0) br##.##call##.##sptk brp = KeScrubBackingStoreRegisters ;\
  562. ;; ;\
  563. alloc rTH1 = 0,0,0,0 ;\
  564. ;; ;\
  565. ;\
  566. loadrs /* pull in user regs */;\
  567. ;; ;\
  568. ;\
  569. Label##KernelExit: ;\
  570. (pUstk) mov ar##.##bspstore = rHBSPSTORE /* restore user BSP */ ;\
  571. dep rHRSC = r0, rHRSC, RSC_MBZ1, RSC_LOADRS_LEN ;\
  572. (pKstk) cmp##.##ne##.##unc pKDbg, pt2 = rHpT1, r0 /* hardware debug? */ ;\
  573. ;\
  574. add rHpT4 = TrApUNAT, sp /* -> previous UNAT */;\
  575. mov ar##.##pfs = rHPFS /* restore PFS */;\
  576. add rHIFS = TrStIFS, sp ;\
  577. ;; ;\
  578. ;\
  579. (pUstk) mov ar##.##rnat = rHRNAT2 /* restore user RNAT */;\
  580. ld8 rHIFS = [rHIFS] /* load IFS */;\
  581. add rHpT1 = TrStIIPA, sp ;\
  582. ;; ;\
  583. ;\
  584. mov ar##.##rsc = rHRSC /* restore user RSC */;\
  585. ld8 rHUNAT = [rHpT4],TrPreds-TrApUNAT ;\
  586. mov brp = rHBrp ;\
  587. ;; ;\
  588. ;\
  589. ld8 rHIIPA = [rHpT1], TrStIIP-TrStIIPA ;\
  590. ld8 rHOldPreds = [rHpT4], TrIntSp-TrPreds ;\
  591. (pt2) dep rHIPSR = 0, rHIPSR, PSR_DB, 1 ;\
  592. ;; ;\
  593. ;\
  594. ld8 rHIIP = [rHpT1], TrStIFS-TrStIIP /* load IIP */;\
  595. ld8##.##fill sp = [rHpT4], TrStIFS-TrIntSp ;\
  596. (pKDbg) dep rHIPSR = 1, rHIPSR, PSR_DB, 1 ;\
  597. ;\
  598. rsm 1 << PSR_IC /* reset ic bit */;\
  599. ;; ;\
  600. srlz##.##d /* must serialize */;\
  601. ;\
  602. /* */;\
  603. /* Restore status registers */;\
  604. /* */;\
  605. ;\
  606. mov cr##.##ipsr = rHIPSR /* restore previous IPSR */;\
  607. mov cr##.##iipa = rHIIPA /* restore previous IIPA */;\
  608. ;\
  609. mov cr##.##ifs = rHIFS /* restore previous IFS */;\
  610. mov cr##.##iip = rHIIP /* restore previous IIP */;\
  611. mov pr = rHOldPreds, -1 /* restore preds */;\
  612. ;; ;\
  613. ;\
  614. /* */;\
  615. /* Resume at point of interruption (rfi must be at end of instruction group)*/;\
  616. /* */;\
  617. mov ar##.##unat = rHUNAT /* restore UNAT */;\
  618. mov h17 = r0 /* clear TB loop count */;\
  619. rfi ;\
  620. ;;
  621. //
  622. // Interruption Vector Table. First level interruption vectors.
  623. // This section must be 32K aligned. The special section ".drectve"
  624. // is used to pass the align command to the linker.
  625. //
  626. .section .drectve, "MI", "progbits"
  627. string "-section:.ivt,,align=0x8000"
  628. .section .ivt = "ax", "progbits"
  629. KiIvtBase:: // symbol for start of IVT
  630. //++
  631. //
  632. // KiVhptTransVector
  633. //
  634. // Cause: The hardware VHPT walker encountered a TLB miss while attempting to
  635. // reference the virtuall addressed VHPT linear table.
  636. //
  637. // Parameters: cr.iip - address of bundle for which the hardware VHPT walker was
  638. // trying to resolve the TLB miss
  639. //
  640. // cr.ipsr - copy of PSR at the time of the fault
  641. //
  642. // cr.idtr - default translation inforamtion for the address that caused
  643. // a VHPT translation fault
  644. //
  645. // cr.ifa - original faulting address
  646. //
  647. // cr.isr - original faulting status information
  648. //
  649. // Handle: Extracts the PDE index from cr.iha (PTE address in VHPT) and
  650. // generates a PDE address by adding to VHPT_DIRBASE. When accesses
  651. // a page directory entry (PDE), there might be a TLB miss on the
  652. // page directory table and returns a NaT on ld8.s. If so, branches
  653. // to KiPageDirectoryTableFault. If the page-not-present bit of the
  654. // PDE is not set, branches to KiPageNotPresentFault. Otherwise,
  655. // inserts the PDE entry into the data TC (translation cache).
  656. //
  657. //--
  658. VECTOR_ENTRY(0x0000, KiVhptTransVector, cr.ifa)
  659. #if 1
  660. rva = h24
  661. riha = h25
  662. rpr = h26
  663. rPte = h27
  664. rK5 = h28
  665. rPte2 = h28
  666. rCache = h28
  667. rps = h29
  668. risr = h30
  669. riha2 = h31
  670. mov rva = cr.ifa // M0
  671. mov rps = PAGE_SIZE
  672. mov riha = cr.iha // M0
  673. mov rpr = pr // I
  674. mov risr = cr.isr // M0
  675. ;;
  676. mov rK5 = ar.k5
  677. tbit.nz pt6 = risr, ISR_SP
  678. ;;
  679. #ifndef NO_IHA_CHECK
  680. thash riha2 = rva // M0, for extra IHA checking
  681. #endif
  682. (pt6) cmp.gtu.unc pt6 = rps, rva
  683. (pt6) br.cond.spnt KiPageZeroFault
  684. ld8.s rPte = [riha] // M
  685. tbit.z pt3, pt4 = risr, ISR_X // I
  686. cmp.le pt7,pt8 = 20, rK5
  687. add rK5 = 2, rK5
  688. ;;
  689. (pt7) mov ar.k5 = r0
  690. tnat.nz pt0 = rPte // I
  691. (pt8) mov ar.k5 = rK5
  692. tbit.z pt1 = rPte, PTE_VALID // I
  693. (pt0) br.cond.spnt KiPageTableFault // B
  694. (pt1) br.cond.spnt KiPteNotPresentFault // B
  695. extr.u rCache = rPte, 2, 3 // I
  696. ;;
  697. cmp.eq pt5 = 1, rCache // A
  698. (pt5) br.cond.spnt KiPageTableFault // B
  699. ;;
  700. .pred.rel "mutex",pt3,pt4
  701. (pt4) itc.i rPte // M
  702. ;;
  703. (pt3) itc.d rPte // M
  704. ;;
  705. #if !defined(NT_UP)
  706. ld8.s rPte2 = [riha] // M
  707. mov rps = PAGE_SHIFT << PS_SHIFT // I
  708. cmp.ne pt0 = zero, zero // I
  709. ;;
  710. cmp.ne.or pt0 = rPte2, rPte // M
  711. #ifndef NO_IHA_CHECK
  712. cmp.ne.or pt0 = riha, riha2 // M, check if IHA is correct
  713. #endif
  714. tnat.nz.or pt0 = rPte2 // I
  715. ;;
  716. (pt0) ptc.l rva, rps // M
  717. #else
  718. #ifndef NO_IHA_CHECK
  719. cmp.ne pt0 = riha, riha2 // M, check if IHA is correct
  720. mov rps = PAGE_SHIFT << PS_SHIFT // I
  721. ;;
  722. (pt0) ptc.l rva, rps // M
  723. #endif
  724. #endif
  725. mov pr = rpr, -1 // I
  726. rfi;; // B
  727. #else
  728. rva = h24
  729. riha = h25
  730. rpr = h26
  731. rpPde = h27
  732. rPde = h28
  733. rPde2 = h29
  734. rps = h30
  735. mov riha = cr.iha // M
  736. mov rva = cr.ifa // M
  737. mov rpr = pr // I
  738. ;;
  739. thash rpPde = riha // M
  740. ;;
  741. ld8.s rPde = [rpPde] // M, load PDE
  742. ;;
  743. tnat.nz pt0, p0 = rPde // I
  744. tbit.z pt1, p0 = rPde, PTE_VALID // I, if non-present page fault
  745. (pt0) br.cond.spnt KiPageDirectoryFault // B
  746. (pt1) br.cond.spnt KiPdeNotPresentFault // B
  747. mov cr.ifa = riha // M
  748. ;;
  749. itc.d rPde // M
  750. ;;
  751. #if !defined(NT_UP)
  752. ld8.s rPde2 = [rpPde] // M
  753. mov rps = PAGE_SHIFT << PS_SHIFT // I
  754. cmp.ne pt0 = zero, zero // I
  755. ;;
  756. cmp.ne.or pt0 = rPde2, rPde // M, if PTEs are different
  757. tnat.nz.or pt0 = rPde2 // I
  758. ;;
  759. (pt0) ptc.l riha, rps // M, purge it
  760. #endif
  761. mov pr = rpr, -1 // I
  762. rfi // B
  763. ;;
  764. #endif
  765. VECTOR_EXIT(KiVhptTransVector)
  766. //++
  767. //
  768. // KiInstTlbVector
  769. //
  770. // Cause: The VHPT walker aborted the search for the instruction translation.
  771. //
  772. // Parameters: cr.iip - address of bundle for which the hardware VHPT walker was
  773. // trying to resolve the TLB miss
  774. //
  775. // cr.ipsr - copy of PSR at the time of the fault
  776. //
  777. // cr.iha - PTE address in the VHPT which the VHPT walker was attempting to
  778. // reference
  779. //
  780. // cr.iitr - default translation inforamtion for the address that caused
  781. // a instruction TLB miss
  782. //
  783. // cr.isr - faulting status information
  784. //
  785. // Handle: As the VHPT has aborted the search or the implemenation does not
  786. // support the h/w page table walk, the handler needs to emulates the
  787. // function. Since the offending PTE address is already available
  788. // with cr.iha, the handler can access the PTE without performing THASH.
  789. // Accessing a PTE with ld8.s may return a NaT. If so, it branches to
  790. // KiPageTableFault. If the page-not-present bit of the PTE is not set,
  791. // it branches to KiPageFault.
  792. //
  793. // Comments: Merced never casues this fault since it never abort the search on the
  794. // VHPT.
  795. //
  796. //--
  797. VECTOR_ENTRY(0x0400, KiInstTlbVector, cr.iipa)
  798. rva = h24
  799. riha = h25
  800. rpr = h26
  801. rPte = h27
  802. rPte2 = h28
  803. rps = h29
  804. rCache = h28
  805. KiInstTlbVector0:
  806. mov riha = cr.iha // M
  807. mov rva = cr.ifa // M
  808. mov rpr = pr // I
  809. ;;
  810. ld8.s rPte = [riha] // M
  811. ;;
  812. tnat.nz pt0, p0 = rPte // I
  813. tbit.z pt1, p0 = rPte, PTE_VALID // I
  814. (pt0) br.cond.spnt KiPageTableFault // B
  815. (pt1) br.cond.spnt KiPteNotPresentFault // B
  816. extr.u rCache = rPte, 2, 3 // I
  817. ;;
  818. cmp.eq pt3 = 1, rCache // A
  819. (pt3) br.cond.spnt Ki4KInstTlbFault // B
  820. itc.i rPte // M
  821. ;;
  822. #if !defined(NT_UP)
  823. ld8.s rPte2 = [riha] // M
  824. mov rps = PAGE_SHIFT << PS_SHIFT // I
  825. cmp.ne pt0 = zero, zero // I
  826. ;;
  827. cmp.ne.or pt0 = rPte2, rPte // M
  828. tnat.nz.or pt0 = rPte2 // I
  829. ;;
  830. (pt0) ptc.l rva, rps // M
  831. #endif
  832. mov pr = rpr, -1 // I
  833. rfi;; // B
  834. VECTOR_EXIT(KiInstTlbVector)
  835. //++
  836. //
  837. // KiDataTlbVector
  838. //
  839. // Cause: The VHPT walker aborted the search for the data translation.
  840. //
  841. // Parameters: cr.iip - address of bundle for which the hardware VHPT walker was
  842. // trying to resolve the TLB miss
  843. //
  844. // cr.ipsr - copy of PSR at the time of the fault
  845. //
  846. // cr.iha - PTE address in the VHPT which the VHPT walker was attempting to
  847. // reference
  848. //
  849. // cr.idtr - default translation inforamtion for the address that caused
  850. // a data TLB miss
  851. //
  852. // cr.ifa - address that caused a data TLB miss
  853. //
  854. // cr.isr - faulting status information
  855. //
  856. // Handle: As the VHPT has aborted the search or the implemenation does not
  857. // support the h/w page table walk, the handler needs to emulates the
  858. // function. Since the offending PTE address is already available
  859. // with cr.iha, the handler can access the PTE without performing THASH.
  860. // Accessing a PTE with ld8.s may return a NaT. If so, it branches to
  861. // KiPageTableFault. If the page-not-present bit of the PTE is not set,
  862. // it branches to KiPageFault.
  863. //
  864. // Comments: Merced never casues instruction TLB faults since the VHPT search always
  865. // sucesses.
  866. //
  867. //--
  868. VECTOR_ENTRY(0x0800, KiDataTlbVector, cr.ifa)
  869. rva = h24
  870. riha = h25
  871. rpr = h26
  872. rPte = h27
  873. rK5 = h28
  874. rPte2 = h28
  875. rCache = h28
  876. rps = h29
  877. KiDataTlbVector0:
  878. mov riha = cr.iha // M
  879. mov rps = PAGE_SIZE
  880. mov rva = cr.ifa // M
  881. mov rpr = pr // I
  882. ;;
  883. mov rK5 = ar.k5
  884. tbit.nz pt6 = risr, ISR_SP
  885. ;;
  886. (pt6) cmp.gtu.unc pt6 = rps, rva
  887. (pt6) br.cond.spnt KiPageZeroFault
  888. ld8.s rPte = [riha] // M
  889. cmp.le pt7,pt8 = 20, rK5
  890. add rK5 = 2, rK5
  891. ;;
  892. (pt7) mov ar.k5 = r0
  893. (pt8) mov ar.k5 = rK5
  894. extr.u rCache = rPte, 2, 3 // I
  895. ;;
  896. cmp.eq pt3 = 1, rCache // A
  897. (pt3) br.cond.spnt Ki4KDataTlbFault // B
  898. tnat.nz pt0, p0 = rPte // I
  899. tbit.z pt1, p0 = rPte, PTE_VALID // I
  900. (pt0) br.cond.spnt KiPageTableFault // B
  901. (pt1) br.cond.spnt KiPteNotPresentFault // B
  902. itc.d rPte // M
  903. ;;
  904. #if !defined(NT_UP)
  905. ld8.s rPte2 = [riha] // M
  906. mov rps = PAGE_SHIFT << PS_SHIFT // I
  907. cmp.ne pt0 = zero, zero // I
  908. ;;
  909. cmp.ne.or pt0 = rPte2, rPte // M
  910. tnat.nz.or pt0 = rPte2 // I
  911. ;;
  912. (pt0) ptc.l rva, rps // M
  913. #endif
  914. mov pr = rpr, -1 // I
  915. rfi;; // B
  916. VECTOR_EXIT(KiDataTlbVector)
  917. //++
  918. //
  919. // KiAltTlbVector
  920. //
  921. // Cause: There was a TLB miss for instruction execution and the VHPT
  922. // walker was not enabled for the referenced region.
  923. //
  924. // Parameters: cr.iip - address of bundle that caused a TLB miss
  925. //
  926. // cr.ipsr - copy of PSR at the time of the fault
  927. //
  928. // cr.idtr - default translation inforamtion for the address that caused
  929. // the fault.
  930. //
  931. // cr.isr - faulting status information
  932. //
  933. // Handle: Currently, NT does not have any use of this vector.
  934. //
  935. //--
  936. VECTOR_ENTRY(0x0c00, KiAltInstTlbVector, cr.iipa)
  937. rva = h24
  938. riha = h25
  939. mov rva = cr.ifa
  940. ;;
  941. thash riha = rva
  942. ;;
  943. mov cr.iha = riha
  944. ;;
  945. srlz.d
  946. br.sptk KiInstTlbVector0
  947. VECTOR_CALL_HANDLER(KiGenericExceptionHandler, KiMemoryFault)
  948. VECTOR_EXIT(KiAltInstTlbVector)
  949. //++
  950. //
  951. // KiAltDataTlbVector
  952. //
  953. // Cause: There was a data TLB miss and the VHPT walker was not enabled for
  954. // the referenced region.
  955. //
  956. // Parameters: cr.iip - address of bundle that caused a TLB miss
  957. //
  958. // cr.ipsr - copy of PSR at the time of the fault
  959. //
  960. // cr.idtr - default translation inforamtion for the address that caused
  961. // the fault.
  962. //
  963. // cr.isr - faulting status information
  964. //
  965. // Handle: Currently, NT does not have any use of this vector.
  966. //
  967. //--
  968. VECTOR_ENTRY(0x1000, KiAltDataTlbVector, cr.ifa)
  969. rva = h24
  970. riha = h25
  971. rpr = h26
  972. rPte = h27
  973. rKseglimit = h28
  974. rIPSR = h30
  975. rISR = h29
  976. rVrn = h31
  977. #if NO_VHPT_WALKER
  978. rRR = h30
  979. mov rva = cr.ifa // M
  980. mov rpr = pr // I
  981. ;;
  982. mov rRR = rr[rva]
  983. movl rKseglimit = KSEG3_LIMIT
  984. ;;
  985. thash riha = rva
  986. tbit.z pt4 = rRR, 0
  987. mov rIPSR = cr.ipsr
  988. shr.u rVrn = rva, VRN_SHIFT // I, get VPN
  989. (pt4) br.cond.spnt AltFault
  990. ;;
  991. mov cr.iha = riha
  992. ;;
  993. srlz.d
  994. mov pr = rpr, -1
  995. br.sptk KiDataTlbVector0
  996. ;;
  997. AltFault:
  998. #else
  999. mov rva = cr.ifa // M
  1000. movl rKseglimit = KSEG3_LIMIT
  1001. ;;
  1002. mov rIPSR = cr.ipsr
  1003. mov rpr = pr // I
  1004. shr.u rVrn = rva, VRN_SHIFT // I, get VPN
  1005. ;;
  1006. #endif
  1007. extr.u rIPSR = rIPSR, PSR_CPL, PSR_CPL_LEN
  1008. ;;
  1009. cmp.ne pt1 = PL_KERNEL, rIPSR
  1010. cmp.ne pt2 = KSEG3_VRN, rVrn // M/I
  1011. cmp.eq pt4 = KSEG4_VRN, rVrn
  1012. (pt1) br.cond.spnt KiCallMemoryFault // if it was User
  1013. (pt4) br.cond.spnt KiKseg4Fault
  1014. (pt2) br.cond.spnt NoKsegFault // B
  1015. cmp.leu pt0 = rKseglimit, rva
  1016. (pt0) br.cond.spnt NoKsegFault
  1017. mov rISR = cr.isr // M
  1018. movl rPte = VALID_KERNEL_PTE // L
  1019. mov rIPSR = cr.ipsr // M
  1020. shr.u rva = rva, PAGE_SHIFT // I
  1021. ;;
  1022. tbit.z pt2, pt3 = rISR, ISR_SP // I
  1023. dep.z rva = rva, PAGE_SHIFT, 32 // I
  1024. ;;
  1025. or rPte = rPte, rva // I
  1026. dep rIPSR = 1, rIPSR, PSR_ED, 1 // I
  1027. ;;
  1028. (pt2) itc.d rPte // M
  1029. ;;
  1030. (pt3) mov cr.ipsr = rIPSR // M
  1031. ;;
  1032. mov pr = rpr, -1 // I
  1033. rfi // B
  1034. ;;
  1035. NoKsegFault:
  1036. rPdeUtbase = h27
  1037. rva0 = h29
  1038. rPpe = h30
  1039. shr.u rva0 = rva, PAGE_SHIFT
  1040. movl rPdeUtbase = KiPcr+PcPdeUtbase
  1041. ;;
  1042. dep.z rva0 = rva0, PAGE_SHIFT, VRN_SHIFT-PAGE_SHIFT
  1043. ld8 rPdeUtbase = [rPdeUtbase]
  1044. movl rPpe = MiDefaultPpe
  1045. ;;
  1046. ld8 rPpe = [rPpe]
  1047. cmp.ne pt3, p0 = rva0, rPdeUtbase
  1048. (pt3) br.cond.spnt KiPageFault
  1049. ;;
  1050. itc.d rPpe
  1051. ;;
  1052. mov pr = rpr, -1
  1053. rfi;;
  1054. VECTOR_EXIT(KiAltDataTlbVector)
  1055. //++
  1056. //
  1057. // KiNestedTlbVector
  1058. //
  1059. // Cause: Instruction/Data TLB miss handler encountered a TLB miss while
  1060. // attempting to reference the PTE in the virtuall addressed
  1061. // VHPT linear table.
  1062. //
  1063. // Parameters: cr.iip - address of bundle for which the hardware VHPT walker was
  1064. // trying to resolve the TLB miss
  1065. //
  1066. // cr.ipsr - copy of PSR at the time of VHPT translation fault
  1067. //
  1068. // cr.iha - address in VHPT which the VHPT walker was attempting to
  1069. // reference
  1070. //
  1071. // cr.idtr - default translation inforamtion for the virtual address
  1072. // contained in cr.iha
  1073. //
  1074. // cr.ifa - original faulting address
  1075. //
  1076. // cr.isr - faulting status information
  1077. //
  1078. // h16(riha) - PTE address in the VHPT which caused the Nested miss
  1079. //
  1080. // Handle: Currently, there is no use for Nested TLB vector. This should be
  1081. // a bug fault. Call KiPanicHandler.
  1082. //
  1083. //--
  1084. VECTOR_ENTRY(0x1400, KiNestedTlbVector, cr.ifa)
  1085. ALLOCATE_TRAP_FRAME
  1086. mov rHIFA = cr.ifa
  1087. br.sptk KiPanicHandler
  1088. VECTOR_EXIT(KiNestedTlbVector)
  1089. //++
  1090. //
  1091. // KiInstKeyMissVector
  1092. //
  1093. // Cause: There was a instruction key miss in the translation. Since the
  1094. // architecture allows an implementation to choose a unified TC
  1095. // structure, the hyper space translation brought by the data
  1096. // access-bit may cause a instruction key miss fault. Only erroneous
  1097. // user code tries to execute the NT page table and hyper space.
  1098. //
  1099. // Parameters: cr.iip - address of bundle which caused a instruction key miss fault
  1100. //
  1101. // cr.ipsr - copy of PSR at the time of the data key miss fault
  1102. //
  1103. // cr.idtr - default translation inforamtion of the address that caused
  1104. // the fault.
  1105. //
  1106. // cr.isr - faulting status information
  1107. //
  1108. // Handle: Save the whole register state and call MmAccessFault().
  1109. //
  1110. //--
  1111. VECTOR_ENTRY(0x1800, KiInstKeyMissVector, cr.iipa)
  1112. VECTOR_CALL_HANDLER(KiGenericExceptionHandler, KiMemoryFault)
  1113. VECTOR_EXIT(KiInstKeyMissVector)
  1114. //++
  1115. //
  1116. // KiDataKeyMissVector
  1117. //
  1118. // Cause: The referenced translation had the different key ID from the one
  1119. // specified the key permission register. This is an indication of
  1120. // TLB miss on the NT page table and hyperspace.
  1121. //
  1122. // Parameters: cr.iip - address of bundle which caused the fault
  1123. //
  1124. // cr.ipsr - copy of PSR at the time of the data key miss fault
  1125. //
  1126. // cr.idtr - default translation inforamtion of the address that caused
  1127. // the fault.
  1128. //
  1129. // cr.ifa - address that caused a data key miss
  1130. //
  1131. // cr.isr - faulting status information
  1132. //
  1133. // Handle: The handler needs to purge the faulting translation and install
  1134. // a new PTE by loading it from the VHPT. The key ID of the IDTR
  1135. // for the installing translation should be modified to be the same
  1136. // ID as the local region ID. This effectively creates a local
  1137. // space within the global kernel space.
  1138. //
  1139. //--
  1140. VECTOR_ENTRY(0x1c00, KiDataKeyMissVector, cr.ifa)
  1141. VECTOR_CALL_HANDLER(KiGenericExceptionHandler, KiMemoryFault)
  1142. VECTOR_EXIT(KiDataKeyMissVector)
  1143. //++
  1144. //
  1145. // KiDirtyBitVector
  1146. //
  1147. // Cause: The refereced data translation did not have the dirty-bit set and
  1148. // a write operation was made to this page.
  1149. //
  1150. // Parameters: cr.iip - address of bundle which caused a dirty bit fault
  1151. //
  1152. // cr.ipsr - copy of PSR at the time of a data access fault
  1153. //
  1154. // cr.idtr - default translation inforamtion for the address that
  1155. // caused the fault
  1156. //
  1157. // cr.ifa - referenced data address that caused the dirty-bit fault
  1158. //
  1159. // cr.isr - faulting status information
  1160. //
  1161. // Handle: Save the whole register state and call MmAccessFault().
  1162. //
  1163. // Comments: There is always a TLB coherency problem on a multiprocessor
  1164. // system. Rather than implementing an atomic operation of setting
  1165. // dirty-bit within this handler, the handler instead calls the high
  1166. // level C routine, MmAccessFault(), to perform locking the page table
  1167. // and setting the dirty-bit of the PTE.
  1168. //
  1169. // It is too much effort to implement the atomic operation of setting
  1170. // the dirty-bit using cmpxchg; a potential nested TLB miss on load/store
  1171. // and restoring ar.ccv complicate the design of the handler.
  1172. //
  1173. //--
  1174. VECTOR_ENTRY(0x2000, KiDirtyBitVector, cr.ifa)
  1175. VECTOR_CALL_HANDLER(KiGenericExceptionHandler, KiMemoryFault)
  1176. VECTOR_EXIT(KiDirtyBitVector)
  1177. //++
  1178. //
  1179. // KiInstAccessBitVector
  1180. //
  1181. // Cause: There is a access-bit fault on the instruction translation. This only
  1182. // happens if the erroneous user mistakenly accesses the NT page table and
  1183. // hyper space.
  1184. //
  1185. // Parameters: cr.iip - address of bundle which caused a instruction access bit fault
  1186. //
  1187. // cr.ipsr - copy of PSR at the time of a data access fault
  1188. //
  1189. // cr.idtr - default translation inforamtion for the address that
  1190. // caused the fault
  1191. //
  1192. // cr.ifa - referenced data address that caused the data access-bit fault
  1193. //
  1194. // cr.isr - faulting status information
  1195. //
  1196. // Handle: Save the whole register state and call MmAccessFault().
  1197. //
  1198. //--
  1199. VECTOR_ENTRY(0x2400, KiInstAccessBitVector, cr.iipa)
  1200. VECTOR_CALL_HANDLER(KiGenericExceptionHandler, KiMemoryFault)
  1201. VECTOR_EXIT(KiInstAccessBitVector)
  1202. //++
  1203. //
  1204. // KiDataBitAccessVector
  1205. //
  1206. // Cause: The reference-bit in the the referenced translation was zero,
  1207. // indicating there was a TLB miss on the NT page table or hyperspace.
  1208. //
  1209. // Parameters: cr.iip - address of bundle which caused a data access bit fault
  1210. //
  1211. // cr.ipsr - copy of PSR at the time of a data access fault
  1212. //
  1213. // cr.idtr - default translation inforamtion for the address that
  1214. // caused the fault
  1215. //
  1216. // cr.ifa - referenced data address that caused the data access-bit fault
  1217. //
  1218. // cr.isr - faulting status information
  1219. //
  1220. // Handle: The reference-bit is used to fault on PTEs for the NT page table and
  1221. // hyperspace. On a data access-bit fault, the handler needs to change the
  1222. // the default key ID of the IDTR to be the local key ID. This effectively
  1223. // creates the local space within the global kernel space.
  1224. //
  1225. //--
  1226. VECTOR_ENTRY(0x2800, KiDataAccessBitVector, cr.ifa)
  1227. rva = h24
  1228. rpr = h26
  1229. rIPSR = h27
  1230. rISR = h31
  1231. //
  1232. // check to see if non-present fault occurred on a speculative load.
  1233. // if so, set IPSR.ed bit. This forces to generate a NaT on ld.s after
  1234. // rfi
  1235. //
  1236. mov rpr = pr
  1237. mov rISR = cr.isr // M
  1238. mov rIPSR = cr.ipsr // M
  1239. ;;
  1240. tbit.z pt0, p0 = rISR, ISR_SP // I
  1241. dep rIPSR = 1, rIPSR, PSR_ED, 1 // I
  1242. (pt0) br.cond.spnt KiCallMemoryFault // B
  1243. ;;
  1244. mov cr.ipsr = rIPSR // M
  1245. ;;
  1246. mov pr = rpr, -1 // I
  1247. rfi // B
  1248. ;;
  1249. VECTOR_EXIT(KiDataBitAccessVector)
  1250. //--------------------------------------------------------------------
  1251. // Routine:
  1252. //
  1253. // KiBreakVector
  1254. //
  1255. // Description:
  1256. //
  1257. // Interruption vector for break instruction.
  1258. //
  1259. // On entry:
  1260. //
  1261. // IIM contains break immediate value:
  1262. // -- BREAK_SYSCALL -> standard system call
  1263. // interrupts disabled
  1264. // r16-r31 switched to kernel bank
  1265. // r16-r31 all available since no TLB faults at this point
  1266. //
  1267. // Return value:
  1268. //
  1269. // if system call, sys call return value in v0.
  1270. //
  1271. // Process:
  1272. //--------------------------------------------------------------------
  1273. VECTOR_ENTRY(0x2C00, KiBreakVector, cr.iim)
  1274. mov rHIIM = cr.iim // get break value
  1275. movl rTH1 = KiPcr+PcSavedIIM
  1276. ;;
  1277. st8 [rTH1] = rHIIM
  1278. VECTOR_CALL_HANDLER(KiGenericExceptionHandler, KiOtherBreakException)
  1279. //
  1280. // Do not return from handler
  1281. //
  1282. VECTOR_EXIT(KiBreakVector)
  1283. //--------------------------------------------------------------------
  1284. // Routine:
  1285. //
  1286. // KiExternalInterruptVector
  1287. //
  1288. // Routine Description:
  1289. //
  1290. // Interruption vector for External Interrrupt
  1291. //
  1292. // On entry:
  1293. //
  1294. // interrupts disabled
  1295. // r16-r31 switched to kernel bank
  1296. //
  1297. // Return value:
  1298. //
  1299. // none
  1300. //
  1301. // Process:
  1302. //--------------------------------------------------------------------
  1303. VECTOR_ENTRY(0x3000, KiExternalInterruptVector, r0)
  1304. mov h24 = cr.iip
  1305. movl h25 = MM_EPC_VA+0x20
  1306. ;;
  1307. mov h26 = pr
  1308. cmp.ne pt0 = h25, h24
  1309. add h25 = 0x10, h25
  1310. ;;
  1311. mov h27 = cr.ipsr
  1312. (pt0) cmp.ne pt0 = h25, h24
  1313. ;;
  1314. dep h27 = 0, h27, PSR_I, 1
  1315. (pt0) br.cond.sptk kei_taken
  1316. ;;
  1317. mov cr.ipsr = h27
  1318. ;;
  1319. mov pr = h26, -1
  1320. rfi
  1321. ;;
  1322. kei_taken:
  1323. mov pr = h26, -1
  1324. ;;
  1325. ALLOCATE_TRAP_FRAME
  1326. ;;
  1327. SAVE_INTERRUPTION_STATE
  1328. br.many KiExternalInterruptHandler
  1329. ;;
  1330. //
  1331. // Do not return (rfi from handler)
  1332. //
  1333. VECTOR_EXIT(KiExternalInterruptVector)
  1334. //++
  1335. //
  1336. // KiPageNotPresentVector
  1337. //
  1338. // Cause: The translation for the referenced page did not have a present-bit
  1339. // set.
  1340. //
  1341. // Parameters: cr.iip - address of bundle which caused a page not present fault
  1342. //
  1343. // cr.ipsr - copy of PSR at the time of a page not present ault
  1344. //
  1345. // cr.idtr - default translation inforamtion for the address that
  1346. // caused the fault
  1347. //
  1348. // cr.ifa - referenced data address if the fault occurred on the data
  1349. // reference
  1350. //
  1351. // cr.isr - faulting status information
  1352. //
  1353. // Handle: This is the page fault. The handler saves the register context and
  1354. // calls MmAccessFault().
  1355. //
  1356. //--
  1357. VECTOR_ENTRY(0x5000, KiPageNotPresentVector, cr.ifa)
  1358. rva = h24
  1359. riha = h25
  1360. rpr = h26
  1361. rPte = h27
  1362. rps = h29
  1363. mov rva = cr.ifa // M
  1364. mov rpr = pr // I
  1365. ;;
  1366. thash riha = rva // M
  1367. cmp.ne pt1 = r0, r0
  1368. mov rps = PAGE_SHIFT << PS_SHIFT // I
  1369. ;;
  1370. ld8.s rPte = [riha] // M
  1371. ;;
  1372. tnat.nz pt0, p0 = rPte // I
  1373. tbit.z.or pt1, p0 = rPte, PTE_ACCESS
  1374. tbit.z.or pt1, p0 = rPte, PTE_VALID // I, if non-present page fault
  1375. (pt0) br.cond.spnt KiPageTableFault // B
  1376. (pt1) br.cond.spnt KiPteNotPresentFault // B
  1377. //
  1378. // if we find a valid PTE that is speculatively fetched into the TLB
  1379. // then, purge it and return.
  1380. //
  1381. ptc.l rva, rps // M
  1382. ;;
  1383. mov pr = rpr, -1 // I
  1384. rfi;; // B
  1385. VECTOR_EXIT(KiPageNotPresentVector)
  1386. //++
  1387. //
  1388. // KiKeyPermVector
  1389. //
  1390. // Cause: Read, write or execution key permissions were violated.
  1391. //
  1392. // Parameters: cr.iip - address of bundle which caused a key permission fault
  1393. //
  1394. // cr.ipsr - copy of PSR at the time of a key permission fault
  1395. //
  1396. // cr.idtr - default translation inforamtion for the address that
  1397. // caused the fault
  1398. //
  1399. // cr.ifa - referenced data address if the key permission occurred on
  1400. // the data reference
  1401. //
  1402. // cr.isr - faulting status information
  1403. //
  1404. // Handle: This should not happen. The EM/NT does not utilize the key permissions.
  1405. // The handler saves the register state and calls the bug check.
  1406. //
  1407. //--
  1408. VECTOR_ENTRY(0x5100, KiKeyPermVector, cr.ifa)
  1409. VECTOR_CALL_HANDLER(KiGenericExceptionHandler, KiMemoryFault)
  1410. VECTOR_EXIT(KiKeyPermVector)
  1411. //++
  1412. //
  1413. // KiInstAccessRightsVector
  1414. //
  1415. // Cause: The referenced page had a access rights violation.
  1416. //
  1417. // Parameters: cr.iip - address of bundle which caused a data access bit fault
  1418. //
  1419. // cr.ipsr - copy of PSR at the time of a data access fault
  1420. //
  1421. // cr.idtr - default translation inforamtion for the address that
  1422. // caused the fault
  1423. //
  1424. // cr.ifa - referenced data address that caused the data ccess-bit fault
  1425. //
  1426. // cr.isr - faulting status information
  1427. //
  1428. // Handle: The handler saves the register context and calls MmAccessFault().
  1429. //
  1430. //--
  1431. VECTOR_ENTRY(0x5200, KiInstAccessRightsVector, cr.iipa)
  1432. VECTOR_CALL_HANDLER(KiGenericExceptionHandler, KiMemoryFault)
  1433. VECTOR_EXIT(KiInstAccessRightsVector)
  1434. //++
  1435. //
  1436. // KiDataAccessRightsVector
  1437. //
  1438. // Cause: The referenced page had a data access rights violation.
  1439. //
  1440. // Parameters: cr.iip - address of bundle which caused a data access rights fault
  1441. //
  1442. // cr.ipsr - copy of PSR at the time of a data access rights fault
  1443. //
  1444. // cr.idtr - default translation inforamtion for the address that
  1445. // caused the fault
  1446. //
  1447. // cr.ifa - referenced data address that caused the data access rights
  1448. // fault
  1449. //
  1450. // cr.isr - faulting status information
  1451. //
  1452. // Handle: The handler saves the register context and calls MmAccessFault().
  1453. //
  1454. //--
  1455. VECTOR_ENTRY(0x5300, KiDataAccessRightsVector, cr.ifa)
  1456. rva = h24
  1457. rpr = h26
  1458. rIPSR = h27
  1459. rISR = h31
  1460. //
  1461. // check to see if non-present fault occurred on a speculative load.
  1462. // if so, set IPSR.ed bit. This forces to generate a NaT on ld.s after
  1463. // rfi
  1464. //
  1465. mov rpr = pr
  1466. mov rISR = cr.isr // M
  1467. mov rIPSR = cr.ipsr // M
  1468. ;;
  1469. tbit.z pt0, p0 = rISR, ISR_SP // I
  1470. dep rIPSR = 1, rIPSR, PSR_ED, 1 // I
  1471. (pt0) br.cond.spnt KiCallMemoryFault2 // B
  1472. ;;
  1473. mov cr.ipsr = rIPSR // M
  1474. ;;
  1475. mov pr = rpr, -1 // I
  1476. rfi // B
  1477. ;;
  1478. KiCallMemoryFault2:
  1479. mov rHIFA = cr.ifa
  1480. movl rHHandler = KiMemoryFault
  1481. mov pr = rpr, -1
  1482. br.sptk KiGenericExceptionHandler
  1483. VECTOR_EXIT(KiDataAccessRightsVector)
  1484. //--------------------------------------------------------------------
  1485. // Routine:
  1486. //
  1487. // KiGeneralExceptionsVector
  1488. //
  1489. // Description:
  1490. //
  1491. // Interruption vector for General Exceptions
  1492. //
  1493. // On entry:
  1494. // interrupts disabled
  1495. // r16-r31 switched to kernel bank
  1496. //
  1497. // Return value:
  1498. //
  1499. // none
  1500. //
  1501. // Process:
  1502. //--------------------------------------------------------------------
  1503. VECTOR_ENTRY(0x5400, KiGeneralExceptionsVector, cr.isr)
  1504. rPSR_ED = h25
  1505. rpr = h26
  1506. rIPSR = h27
  1507. rCode = h30
  1508. rISR = h31
  1509. rLfetch = h28
  1510. mov rISR = cr.isr // M
  1511. movl rPSR_ED = 1 << PSR_ED // L
  1512. mov rIPSR = cr.ipsr // M
  1513. mov rpr = pr
  1514. ;;
  1515. cmp.ne pt0 = r0, r0
  1516. extr.u rCode = rISR, 0, 8
  1517. mov rLfetch = ISR_LFETCH|ISR_RESVD_REG << 4
  1518. ;;
  1519. cmp.ne.or pt0 = rCode, rLfetch
  1520. tbit.z.or pt0 = rISR, ISR_NA
  1521. (pt0) br.cond.sptk KiCallGeneralExceptions
  1522. ;;
  1523. or rIPSR = rIPSR, rPSR_ED // A
  1524. ;;
  1525. mov cr.ipsr = rIPSR // M
  1526. mov pr = rpr, -1 // I
  1527. ;;
  1528. rfi
  1529. ;;
  1530. KiCallGeneralExceptions:
  1531. mov rHIFA = cr.ifa
  1532. movl rHHandler = KiGeneralExceptions
  1533. mov pr = rpr, -1
  1534. br.sptk KiGenericExceptionHandler
  1535. //
  1536. // Do not return (rfi from handler)
  1537. //
  1538. VECTOR_EXIT(KiGeneralExceptionsVector)
  1539. //--------------------------------------------------------------------
  1540. // Routine:
  1541. //
  1542. // KiDisabledFpRegisterVector
  1543. //
  1544. // Description:
  1545. //
  1546. // Interruption vector for Disabled FP-register vector
  1547. //
  1548. // On entry:
  1549. // interrupts disabled
  1550. // r16-r31 switched to kernel bank
  1551. //
  1552. // Return value:
  1553. //
  1554. // none
  1555. //
  1556. // Process:
  1557. //--------------------------------------------------------------------
  1558. VECTOR_ENTRY(0x5500, KiDisabledFpRegisterVector, cr.isr)
  1559. mov rHIPSR = cr.ipsr
  1560. mov rHIIP = cr.iip
  1561. cover
  1562. ;;
  1563. mov rHIFS = cr.ifs
  1564. extr.u rTH1 = rHIPSR, PSR_CPL, PSR_CPL_LEN
  1565. mov rHOldPreds = pr
  1566. ;;
  1567. cmp4.eq pKrnl, pUser = PL_KERNEL, rTH1
  1568. ;;
  1569. (pUser) tbit.z.unc pt0, pt1 = rHIPSR, PSR_DFH // if dfh not set,
  1570. // dfl must be set
  1571. (pKrnl) br.spnt.few Kdfrv10 // Kernel mode should never get here.
  1572. ;;
  1573. (pt1) ssm 1 << PSR_IC // set ic bit
  1574. (pt1) mov rHDfhPFS = ar.pfs
  1575. (pt1) mov rHDfhBrp = brp
  1576. ;;
  1577. (pt1) srlz.d
  1578. (pt1) br.call.sptk.many brp = KiRestoreHigherFPVolatile
  1579. (pt0) br.spnt.few Kdfrv10
  1580. ;;
  1581. rsm 1 << PSR_IC // reset ic bit
  1582. dep rHIPSR = 0, rHIPSR, PSR_DFH, 1 // reset dfh bit
  1583. mov brp = rHDfhBrp
  1584. ;;
  1585. srlz.d
  1586. mov cr.ifs = rHIFS
  1587. mov ar.pfs = rHDfhPFS
  1588. mov cr.ipsr = rHIPSR
  1589. mov cr.iip = rHIIP
  1590. mov pr = rHOldPreds, -1
  1591. ;;
  1592. rfi
  1593. ;;
  1594. Kdfrv10:
  1595. mov pr = rHOldPreds, -1
  1596. VECTOR_CALL_HANDLER(KiGenericExceptionHandler, KiGeneralExceptions)
  1597. ;;
  1598. VECTOR_EXIT(KiDisabledFpRegisterVector)
  1599. //--------------------------------------------------------------------
  1600. // Routine:
  1601. //
  1602. // KiNatConsumptionVector
  1603. //
  1604. // Description:
  1605. //
  1606. // Interruption vector for Nat Consumption Vector
  1607. //
  1608. // On entry:
  1609. // interrupts disabled
  1610. // r16-r31 switched to kernel bank
  1611. //
  1612. // Return value:
  1613. //
  1614. // none
  1615. //
  1616. // Process:
  1617. //--------------------------------------------------------------------
  1618. VECTOR_ENTRY(0x5600, KiNatConsumptionVector, cr.isr)
  1619. mov h16 = cr.isr
  1620. mov h17 = pr
  1621. ;;
  1622. mov rHIFA = cr.ifa
  1623. extr.u h16 = h16, 4, 4 // extract the error code
  1624. ;;
  1625. cmp.eq pt0, pt1 = ISR_NAT_PAGE, h16
  1626. ;;
  1627. (pt0) movl rHHandler = KiMemoryFault
  1628. (pt1) movl rHHandler = KiNatExceptions
  1629. ;;
  1630. mov pr = h17, -1
  1631. br.sptk KiGenericExceptionHandler
  1632. VECTOR_EXIT(KiNatConsumptionVector)
  1633. //++
  1634. //
  1635. // KiSpeculationVector
  1636. //
  1637. // Cause: CHK.S, CHK.A, FCHK detected an exception condition.
  1638. //
  1639. // Parameters: cr.iip - address of bundle which caused a speculation fault
  1640. //
  1641. // cr.ipsr - copy of PSR at the time of a speculation fault
  1642. //
  1643. // cr.iipa - address of bundle containing the last
  1644. // successfully executed instruction
  1645. //
  1646. // cr.iim - contains the immediate value in either
  1647. // CHK.S, CHK.A, or FCHK opecode
  1648. //
  1649. // cr.isr - faulting status information
  1650. //
  1651. // Handle: The handler implements a branch operation to the
  1652. // recovery code specified by the IIM IP-offset.
  1653. //
  1654. // Note: This code will not be exercised until the compiler
  1655. // generates the speculation code.
  1656. //
  1657. // TBD: Need to check for taken branch trap.
  1658. //
  1659. //--
  1660. VECTOR_ENTRY(0x5700, KiSpeculationVector, cr.iim)
  1661. mov h16 = cr.iim // get imm offset
  1662. mov h17 = cr.iip // get IIP
  1663. ;;
  1664. extr h16 = h16, 0, 21 // get sign-extended
  1665. mov h18 = cr.ipsr
  1666. ;;
  1667. shladd h16 = h16, 4, h17 // get addr for recovery handler
  1668. dep h18 = 0, h18, PSR_RI, 2 // zero target slot number
  1669. ;;
  1670. mov cr.ipsr = h18
  1671. mov cr.iip = h16
  1672. ;;
  1673. rfi
  1674. ;;
  1675. VECTOR_EXIT(KiSpeculationVector)
  1676. //++
  1677. //
  1678. // KiDebugFaultVector
  1679. //
  1680. // Cause: A unaligned data access fault has occured
  1681. //
  1682. // Parameters: cr.iip - address of bundle causing the fault.
  1683. //
  1684. // cr.ipsr - copy of PSR at the time of interruption.
  1685. //
  1686. // cr.iipa - address of bundle containing the last
  1687. // successfully executed instruction
  1688. //
  1689. // cr.isr - faulting status information. ISR.ei bits are
  1690. // set to indicate which instruction caused the
  1691. // exception.
  1692. // The ISR.code contains information about the
  1693. // FP exception fault. See trapc.c and the EAS
  1694. //
  1695. //--
  1696. VECTOR_ENTRY(0x5900, KiDebugFaultVector, cr.isr)
  1697. VECTOR_CALL_HANDLER(KiGenericExceptionHandler, KiDebugFault)
  1698. //
  1699. // Do not return (rfi from handler)
  1700. //
  1701. VECTOR_EXIT(KiDebugFaultVector)
  1702. //++
  1703. //
  1704. // KiUnalignedFaultVector
  1705. //
  1706. // Cause: A unaligned data access fault has occured
  1707. //
  1708. // Parameters: cr.iip - address of bundle causing the fault.
  1709. //
  1710. // cr.ipsr - copy of PSR at the time of interruption.
  1711. //
  1712. // cr.iipa - address of bundle containing the last
  1713. // successfully executed instruction
  1714. //
  1715. // cr.isr - faulting status information. ISR.ei bits are
  1716. // set to indicate which instruction caused the
  1717. // exception.
  1718. // The ISR.code contains information about the
  1719. // FP exception fault. See trapc.c and the EAS
  1720. //
  1721. //--
  1722. VECTOR_ENTRY(0x5a00, KiUnalignedFaultVector, cr.ifa)
  1723. VECTOR_CALL_HANDLER(KiGenericExceptionHandler, KiUnalignedFault)
  1724. //
  1725. // Do not return (rfi from handler)
  1726. //
  1727. VECTOR_EXIT(KiUnalignedFaultVector)
  1728. //++
  1729. //
  1730. // KiFloatFaultVector
  1731. //
  1732. // Cause: A floating point fault has occured
  1733. //
  1734. // Parameters: cr.iip - address of bundle causing the fault.
  1735. //
  1736. // cr.ipsr - copy of PSR at the time of interruption.
  1737. //
  1738. // cr.iipa - address of bundle containing the last
  1739. // successfully executed instruction
  1740. //
  1741. // cr.isr - faulting status information. ISR.ei bits are
  1742. // set to indicate which instruction caused the
  1743. // exception.
  1744. // The ISR.code contains information about the
  1745. // FP exception fault. See trapc.c and the EAS
  1746. //
  1747. //--
  1748. VECTOR_ENTRY(0x5c00, KiFloatFaultVector, cr.isr)
  1749. VECTOR_CALL_HANDLER(KiGenericExceptionHandler, KiFloatFault)
  1750. //
  1751. // Do not return (rfi from handler)
  1752. //
  1753. VECTOR_EXIT(KiFloatFaultVector)
  1754. //++
  1755. //
  1756. // KiFloatTrapVector
  1757. //
  1758. // Cause: A floating point trap has occured
  1759. //
  1760. // Parameters: cr.iip - address of bundle with the instruction to be
  1761. // executed next.
  1762. //
  1763. // cr.ipsr - copy of PSR at the time of interruption.
  1764. //
  1765. // cr.iipa - address of bundle containing the last
  1766. // successfully executed instruction
  1767. //
  1768. // cr.isr - faulting status information. ISR.ei bits are
  1769. // set to indicate which instruction caused the
  1770. // exception.
  1771. // The ISR.code contains information about the
  1772. // FP trap. See trapc.c and the EAS
  1773. //
  1774. //--
  1775. VECTOR_ENTRY(0x5d00, KiFloatTrapVector, cr.isr)
  1776. VECTOR_CALL_HANDLER(KiGenericExceptionHandler, KiFloatTrap)
  1777. //
  1778. // Do not return (rfi from handler)
  1779. //
  1780. VECTOR_EXIT(KiFloatTrapVector)
  1781. //++
  1782. //
  1783. // KiLowerPrivilegeVector
  1784. //
  1785. // Cause: A branch lowers the privilege level and PSR.lp is 1.
  1786. // Or an attempt made to execute an instruction
  1787. // in the unimplemented address space.
  1788. // This trap is higher priority than taken branch
  1789. // or single step traps.
  1790. //
  1791. // Parameters: cr.iip - address of bundle containing the instruction to
  1792. // be executed next.
  1793. //
  1794. // cr.ipsr - copy of PSR at the time of interruption.
  1795. //
  1796. // cr.iipa - address of bundle containing the last
  1797. // successfully executed instruction
  1798. //
  1799. // cr.isr - faulting status information. The ISR.code
  1800. // contains a bit vector for all traps which
  1801. // occurred in the trapping bundle.
  1802. //
  1803. //--
  1804. VECTOR_ENTRY(0x5e00, KiLowerPrivilegeVector, cr.iipa)
  1805. mov rHISR = cr.isr
  1806. mov rHOldPreds = pr
  1807. mov rHIIPA = cr.iipa
  1808. mov rHIPSR = cr.ipsr
  1809. ;;
  1810. tbit.z pt1, pt0 = rHISR, ISR_UI_TRAP
  1811. (pt1) br.cond.spnt Klpv10
  1812. ;;
  1813. mov rHIFA = cr.iip
  1814. movl rHHandler = KiUnimplementedAddressTrap
  1815. mov pr = rHOldPreds, -2 // must restore predicates
  1816. br.sptk KiGenericExceptionHandler
  1817. ;;
  1818. Klpv10:
  1819. mov rHVector = ip
  1820. mov rPanicCode = UNEXPECTED_KERNEL_MODE_TRAP
  1821. br.sptk KiPanicHandler
  1822. VECTOR_EXIT(KiLowerPrivilegeVector)
  1823. //++
  1824. //
  1825. // KiTakenBranchVector
  1826. //
  1827. // Cause: A taken branch was successfully execcuted and the PSR.tb
  1828. // bit is 1. This trap is higher priority than single step trap.
  1829. //
  1830. // Parameters: cr.iip - address of bundle containing the instruction to
  1831. // be executed next.
  1832. //
  1833. // cr.ipsr - copy of PSR at the time of interruption.
  1834. //
  1835. // cr.iipa - address of bundle containing the last
  1836. // successfully executed instruction
  1837. //
  1838. // cr.isr - faulting status information. The ISR.code
  1839. // contains a bit vector for all traps which
  1840. // occurred in the trapping bundle.
  1841. //
  1842. //--
  1843. VECTOR_ENTRY(0x5f00, KiTakenBranchVector, cr.iipa)
  1844. mov rHIPSR = cr.ipsr
  1845. movl rHEPCVa = MM_EPC_VA+0x20 // user system call entry point
  1846. mov rHIIP = cr.iip
  1847. movl rHpT1 = KiPcr+PcInitialStack
  1848. ;;
  1849. ld8 rHpT1 = [rHpT1]
  1850. extr.u rTH1 = rHIPSR, PSR_CPL, PSR_CPL_LEN
  1851. mov rHOldPreds = pr
  1852. ;;
  1853. cmp.eq pt0 = rHEPCVa, rHIIP
  1854. ;;
  1855. (pt0) ssm 1 << PSR_IC
  1856. (pt0) movl rHpT3 = 1 << PSR_LP
  1857. ;;
  1858. (pt0) or rHpT3 = rHIPSR, rHpT3
  1859. (pt0) srlz.d
  1860. add rHpT1=-ThreadStateSaveAreaLength-TrapFrameLength+TrStIPSR,rHpT1
  1861. (pt0) br.spnt.few Ktbv10
  1862. mov pr = rHOldPreds, -2
  1863. VECTOR_CALL_HANDLER(KiGenericExceptionHandler, KiSingleStep)
  1864. ;;
  1865. Ktbv10:
  1866. st8 [rHpT1] = rHpT3
  1867. movl rHpT3 = 1 << PSR_SS | 1 << PSR_TB | 1 << PSR_DB
  1868. ;;
  1869. rsm 1 << PSR_IC
  1870. mov pr = rHOldPreds, -2
  1871. andcm rHIPSR = rHIPSR, rHpT3 // clear ss, tb, db bits
  1872. ;;
  1873. srlz.d
  1874. mov cr.ipsr = rHIPSR
  1875. ;;
  1876. rfi
  1877. ;;
  1878. VECTOR_EXIT(KiTakenBranchVector)
  1879. //++
  1880. //
  1881. // KiSingleStepVector
  1882. //
  1883. // Cause: An instruction was successfully execcuted and the PSR.ss
  1884. // bit is 1.
  1885. //
  1886. // Parameters: cr.iip - address of bundle containing the instruction to
  1887. // be executed next.
  1888. //
  1889. // cr.ipsr - copy of PSR at the time of interruption.
  1890. //
  1891. // cr.iipa - address of bundle containing the last
  1892. // successfully executed instruction
  1893. //
  1894. // cr.isr - faulting status information. The ISR.code
  1895. // contains a bit vector for all traps which
  1896. // occurred in the trapping bundle.
  1897. //
  1898. //--
  1899. VECTOR_ENTRY(0x6000, KiSingleStepVector, cr.iipa)
  1900. mov rHIPSR = cr.ipsr
  1901. movl rHEPCVa = MM_EPC_VA+0x20 // user system call entry point
  1902. mov rHIIP = cr.iip
  1903. movl rHpT1 = KiPcr+PcInitialStack
  1904. ;;
  1905. ld8 rHpT1 = [rHpT1]
  1906. extr.u rTH1 = rHIPSR, PSR_CPL, PSR_CPL_LEN
  1907. mov rHOldPreds = pr
  1908. ;;
  1909. cmp.eq pt0 = rHEPCVa, rHIIP
  1910. ;;
  1911. (pt0) ssm 1 << PSR_IC
  1912. (pt0) movl rHpT3 = 1 << PSR_LP
  1913. ;;
  1914. (pt0) or rHpT3 = rHIPSR, rHpT3
  1915. (pt0) srlz.d
  1916. add rHpT1=-ThreadStateSaveAreaLength-TrapFrameLength+TrStIPSR,rHpT1
  1917. (pt0) br.spnt.few Kssv10
  1918. mov pr = rHOldPreds, -2
  1919. VECTOR_CALL_HANDLER(KiGenericExceptionHandler, KiSingleStep)
  1920. ;;
  1921. Kssv10:
  1922. st8 [rHpT1] = rHpT3
  1923. movl rHpT3 = 1 << PSR_SS | 1 << PSR_DB
  1924. ;;
  1925. rsm 1 << PSR_IC
  1926. mov pr = rHOldPreds, -2
  1927. andcm rHIPSR = rHIPSR, rHpT3 // clear ss, db bits
  1928. ;;
  1929. srlz.d
  1930. mov cr.ipsr = rHIPSR
  1931. ;;
  1932. rfi
  1933. ;;
  1934. VECTOR_EXIT(KiSingleStepVector)
  1935. //++
  1936. //
  1937. // KiIA32ExceptionVector
  1938. //
  1939. // Cause: A fault or trap was generated while executing from the
  1940. // iA-32 instruction set.
  1941. //
  1942. // Parameters: cr.iip - address of the iA-32 instruction causing interruption
  1943. //
  1944. // cr.ipsr - copy of PSR at the time of the instruction
  1945. //
  1946. // cr.iipa - Address of the last successfully executed
  1947. // iA-32 or EM instruction
  1948. //
  1949. // cr.isr - The ISR.ei exception indicator is cleared.
  1950. // ISR.iA_vector contains the iA-32 interruption vector
  1951. // number. ISR.code contains the iA-32 16-bit error cod
  1952. //
  1953. // Handle: Save the whole register state and
  1954. // call KiIA32ExceptionVectorHandler()().
  1955. //
  1956. //--
  1957. VECTOR_ENTRY(0x6900, KiIA32ExceptionVector, r0)
  1958. mov rHIIM = cr.iim // save info from IIM
  1959. movl rTH1 = KiPcr+PcSavedIIM
  1960. ;;
  1961. st8 [rTH1] = rHIIM
  1962. VECTOR_CALL_HANDLER(KiGenericExceptionHandler,
  1963. KiIA32ExceptionVectorHandler)
  1964. VECTOR_EXIT(KiIA32ExceptionVector)
  1965. //++
  1966. //
  1967. // KiIA32InterceptionVector
  1968. //
  1969. // Cause: A interception fault or trap was generated while executing
  1970. // from the iA-32 instruction set.
  1971. //
  1972. // Parameters: cr.iip - address of the iA-32 instruction causing interruption
  1973. //
  1974. // cr.ipsr - copy of PSR at the time of the instruction
  1975. //
  1976. // cr.iipa - Address of the last successfully executed
  1977. // iA-32 or EM instruction
  1978. //
  1979. // cr.isr - The ISR.ei exception indicator is cleared.
  1980. // ISR.iA_vector contains the iA-32 interruption vector
  1981. // number. ISR.code contains the iA-32specific
  1982. // interception information
  1983. //
  1984. // Handle: Save the whole register state and
  1985. // call KiIA32InterceptionVectorHandler()().
  1986. //
  1987. //--
  1988. VECTOR_ENTRY(0x6a00, KiIA32InterceptionVector, r0)
  1989. mov rHIIM = cr.iim // save info from IIM
  1990. movl rTH1 = KiPcr+PcSavedIIM
  1991. ;;
  1992. st8 [rTH1] = rHIIM
  1993. VECTOR_CALL_HANDLER(KiGenericExceptionHandler,
  1994. KiIA32InterceptionVectorHandler)
  1995. VECTOR_EXIT(KiIA32InterceptionVector)
  1996. //++
  1997. //
  1998. // KiIA32InterruptionVector
  1999. //
  2000. // Cause: An iA software interrupt was executed
  2001. //
  2002. // Parameters: cr.iip - address of the iA-32 instruction causing interruption
  2003. //
  2004. // cr.ipsr - copy of PSR at the time of the instruction
  2005. //
  2006. // cr.iipa - Address of the last successfully executed
  2007. // iA-32 or EM instruction
  2008. //
  2009. // cr.isr - ISR.iA_vector contains the iA-32 defined vector
  2010. // number. ISR.code contains 0
  2011. // ISR.ei excepting instruction indicator is cleared.
  2012. // ISR.iA_vector contains the iA-32 instruction vector.
  2013. // ISR.code contains iA-32 specific information.
  2014. //
  2015. // Handle: Save the whole register state and
  2016. // call KiIA32InterruptionVectorHandler()().
  2017. //
  2018. //--
  2019. VECTOR_ENTRY(0x6b00, KiIA32InterruptionVector, r0)
  2020. // This one doesn't need IIM, so we won't bother to save it
  2021. VECTOR_CALL_HANDLER(KiGenericExceptionHandler,
  2022. KiIA32InterruptionVectorHandler)
  2023. VECTOR_EXIT(KiIA32InterruptionVector)
  2024. //
  2025. // All non-VECTOR_ENTRY functions must follow KiNormalSystemCall.
  2026. //
  2027. // N.B. KiNormalSystemCall must be the first function body in the .nsc
  2028. // section.
  2029. //
  2030. //--------------------------------------------------------------------
  2031. // Routine:
  2032. //
  2033. // KiNormalSystemCall
  2034. //
  2035. // Description:
  2036. //
  2037. // Handler for normal (not fast) system calls
  2038. //
  2039. // On entry:
  2040. //
  2041. // ic off
  2042. // interrupts disabled
  2043. // v0: contains sys call #
  2044. // cover done by call
  2045. // r32-r39: sys call arguments
  2046. // CFM: sof = # args, ins = 0, outs = # args
  2047. // clear mfh bit (high fp registers are scratch per s/w convention)
  2048. //
  2049. // Return value:
  2050. //
  2051. // v0: system call return value
  2052. //
  2053. // Process:
  2054. //
  2055. //--------------------------------------------------------------------
  2056. .section .drectve, "MI", "progbits"
  2057. string " -section:.nsc,,align=0x2000"
  2058. .section .nsc = "ax", "progbits"
  2059. HANDLER_ENTRY_EX(KiNormalSystemCall, KiSystemServiceHandler)
  2060. .prologue
  2061. .unwabi @nt, EXCEPTION_FRAME
  2062. rPFS = t0
  2063. rThread = t1 // current thread
  2064. rIFS = t1
  2065. rIIP = t2
  2066. rPreds = t3
  2067. rIPSR = t4
  2068. rUNAT = t5
  2069. rSp = t6
  2070. rpT1 = t7
  2071. rpT2 = t8
  2072. rpT3 = t9
  2073. rpT4 = t10
  2074. rT0 = t11
  2075. rT1 = t12
  2076. rT2 = t13
  2077. rT3 = t14
  2078. rT4 = t15
  2079. rKDbgActive = t16
  2080. rIntNats = t17
  2081. rpSd = t16 /* -> service descriptor entry */
  2082. rArgTable = t18 /* pointer to argument table */
  2083. rArgNum = t20 /* number of arguments */
  2084. rArgBytes = t21
  2085. rRscD = t16
  2086. rRNAT = t17
  2087. rRscE = t18
  2088. rKBSPStore = t18
  2089. rBSPStore = t19
  2090. rRscDelta = t20
  2091. rBSP = t21
  2092. rPreviousMode = t22
  2093. pInvl = ps9 /* pInvl = not GUI service */
  2094. pVal = pt1
  2095. pGui = pt2 /* true if GUI call */
  2096. pNoGui = pt3 /* true if no GUI call */
  2097. pNatedArg = pt4 /* true if any input argument */
  2098. /* register is Nat'ed */
  2099. pNoCopy = pt5 /* no in-memory arguments to copy */
  2100. pCopy = pt6
  2101. pNatedSp = pt7
  2102. mov rUNAT = ar.unat
  2103. mov rPreds = pr
  2104. mov rPreviousMode = KernelMode
  2105. mov rIPSR = psr
  2106. rsm 1 << PSR_I | 1 << PSR_MFH
  2107. br.sptk Knsc_Allocate
  2108. ;;
  2109. //
  2110. // N.B. KiUserSystemCall is at an offset of 0x20 from KiNormalSystemCall.
  2111. // Whenever this offset is changed, the definition of kernel system call
  2112. // stub in services.stb must be updated to reflect the new value.
  2113. //
  2114. ALTERNATE_ENTRY(KiUserSystemCall)
  2115. mov rUNAT = ar.unat
  2116. mov rPreds = pr
  2117. epc
  2118. ;;
  2119. mov rIPSR = psr
  2120. rsm (1 << PSR_I) | (1 << PSR_BE)
  2121. mov rPreviousMode = UserMode
  2122. ;; // stop bit needed to ensure interrupt is off
  2123. Knsc_Allocate::
  2124. #if defined(INTERRUPTION_LOGGING)
  2125. // For Conditional Interrupt Logging
  2126. movl rpT1 = KiVectorLogMask
  2127. ;;
  2128. ld8 rT1 = [rpT1]
  2129. ;;
  2130. tbit.z pt1 = rT1, UserSystemcallBit
  2131. (pt1) br.cond.sptk EndOfLogging1
  2132. mov rT1 = 0x80 // dummy offset for sys call
  2133. movl rpT1 = KiPcr+PcInterruptionCount
  2134. mov rT2 = b0
  2135. mov rT3 = MAX_NUMBER_OF_IHISTORY_RECORDS - 1
  2136. ;;
  2137. ld4.nt1 rT4 = [rpT1] // get current count
  2138. or rT1 = rT1, rPreviousMode // kernel/user
  2139. ;;
  2140. add rT0 = 1, rT4 // incr count
  2141. and rT4 = rT3, rT4 // index of current entry
  2142. add rpT2 = 0x1000-PcInterruptionCount, rpT1 // base of history
  2143. ;;
  2144. st4.nta [rpT1] = rT0 // save count
  2145. shl rT4 = rT4, 5 // offset of current entry
  2146. ;;
  2147. add rpT2 = rpT2, rT4 // address of current entry
  2148. ;;
  2149. st8 [rpT2] = rT1, 8 // save sys call offset
  2150. ;;
  2151. st8 [rpT2] = rT2, 8 // save return address
  2152. ;;
  2153. st8 [rpT2] = rIPSR, 8 // save psr
  2154. ;;
  2155. st8.spill [rpT2] = v0; // save sys call number
  2156. ;;
  2157. // For Conditional Interrupt Logging
  2158. EndOfLogging1:
  2159. #endif // INTERRUPTION_LOGGING
  2160. //
  2161. // if sp is Nat'ed return to caller with an error status
  2162. // N.B. sp is spilled and a value of zero is saved in the IntNats field
  2163. //
  2164. tnat.nz pNatedSp = sp
  2165. movl rpT4 = KiPcr+PcInitialStack
  2166. ;;
  2167. mov rSp = sp
  2168. (pNatedSp) movl rT4 = Knsc_ErrorReturn
  2169. ;;
  2170. tnat.nz pNatedArg = v0 // Test service number for NAT.
  2171. cmp.eq pUser, pKrnl = UserMode, rPreviousMode
  2172. mov rBSP = ar.bsp
  2173. (pNatedSp) movl v0 = STATUS_IA64_INVALID_STACK
  2174. ;;
  2175. (pUser) ld8 sp = [rpT4], PcInitialBStore-PcInitialStack // set new sp
  2176. mov rIIP = brp
  2177. mov rPFS = ar.pfs
  2178. ;;
  2179. mov rT2 = ar.rsc
  2180. (pUser) ld8 rKBSPStore = [rpT4], PcKernelDebugActive-PcInitialBStore
  2181. (pNatedSp) mov bt1 = rT4
  2182. ;;
  2183. (pUser) ld1 rKDbgActive = [rpT4], PcCurrentThread-PcKernelDebugActive
  2184. (pKrnl) add rpT4 = PcCurrentThread-PcInitialStack, rpT4
  2185. extr.u rIFS = rPFS, 0, 38
  2186. mov rT0 = ar.fpsr
  2187. (pUser) movl rT3 = 1 << PSR_SS | 1 << PSR_DB | 1 << PSR_TB | 1 << PSR_LP
  2188. (pUser) mov ar.rsc = r0 // put RSE in lazy mode
  2189. (pUser) add sp = -ThreadStateSaveAreaLength-TrapFrameLength, sp
  2190. (pKrnl) add sp = -TrapFrameLength, sp // allocate TF
  2191. ;;
  2192. (pUser) mov rBSPStore = ar.bspstore // get user bsp store point
  2193. add rpT1 = TrStIPSR, sp // -> IPSR
  2194. add rpT2 = TrIntSp, sp // -> IntSp
  2195. ;;
  2196. //
  2197. // Get the previous value of the IPRS from the stack. This is used to get user's debug
  2198. // values TB, SS, and DB from before they call the system service. KiSingleStepVector and
  2199. // KiTakenBranchVector clear these bits if they hit on the EPC instruction. This value is
  2200. // initialized to zero at thread startup and then copied if the user trap frame moves because
  2201. // of stack convertion or user call backs.
  2202. //
  2203. (pUser) ld8 rT4 = [rpT1]
  2204. st8.spill [rpT2] = rSp, TrApUNAT-TrIntSp // sp is not Nat'ed
  2205. add rpT3 = TrStIFS, sp // -> IFS
  2206. (pNatedArg) mov v0 = SERVICE_NUMBER_MASK // v0 is NATed set it to the maximum system service number.
  2207. dep rIFS = 1, rIFS, 63, 1 // set IFS.v
  2208. ;;
  2209. st8 [rpT2] = rUNAT, TrPreds-TrApUNAT
  2210. st8 [rpT3] = rIFS, TrRsPFS-TrStIFS // save IFS
  2211. (pUser) and rT4 = rT3, rT4 // capture psr.db, tb, ss
  2212. ;;
  2213. st8 [rpT2] = rPreds, TrIntNats-TrPreds
  2214. st8.nta [rpT3] = rPFS, TrStFPSR-TrRsPFS // save PFS
  2215. (pUser) mov rT3 = rIPSR
  2216. rBspOff = t5
  2217. extr.u rBspOff = rBSP, 0, 9
  2218. extr.u t0 = rIFS, 0, 7
  2219. extr.u rIFS = rIFS, 7, 7
  2220. ;;
  2221. (pUser) mov rRNAT = ar.rnat
  2222. movl rT1 = 1 << PSR_I | 1 << PSR_MFH | 1 << PSR_BE
  2223. sub rIFS = t0, rIFS
  2224. movl t0 = 1 << PSR_I | 1 << PSR_BN
  2225. ;;
  2226. (pUser) or rIPSR = rIPSR, rT4
  2227. (pUser) cmp.ne.unc pKDbg, pt2 = zero, rKDbgActive // kernel debug active?
  2228. shladd rBspOff = rIFS, 3, rBspOff
  2229. shladd rBSP = rIFS, 3, rBSP
  2230. mov rT4 = 0x1F8
  2231. (pUser) dep t0 = 1, t0, PSR_CPL, 2
  2232. ;;
  2233. st8 [rpT2] = zero,TrIntGp-TrIntNats // all integer Nats are 0
  2234. st8 [rpT3] = rT0, TrStIIP-TrStFPSR // save FPSR
  2235. (pUser) andcm rT3 = rT3, rT1 // clear i, mfh, be
  2236. cmp.ge pt0 = rBspOff, rT4
  2237. or rIPSR = t0, rIPSR // set i, cpl, bn for the saved IPSR
  2238. ;;
  2239. st8 [rpT1] = rIPSR // save IPSR
  2240. st8 [rpT3] = rIIP, TrBrRp-TrStIIP // save IIP
  2241. (pt2) dep rT3 = 0, rT3, PSR_DB, 1 // disable db in kernel
  2242. ;;
  2243. st8.nta [rpT3] = rIIP, TrRsBSP-TrBrRp // save BRP
  2244. st8.spill [rpT2] = gp, TrIntV0-TrIntGp // Save GP even though it is a temporary
  2245. // If someone does a get/set context and GP
  2246. // is zero in the trap fram then set context
  2247. // will think IIP is a plabel and dereference i.
  2248. (pt0) add rBSP = 8, rBSP
  2249. (pUser) dep rT3 = 1, rT3, PSR_AC, 1 // enable alignment check
  2250. ;;
  2251. (pt0) add rIFS = 1, rIFS
  2252. st8.nta [rpT2] = v0, TrRsRSC-TrIntV0 // Sanitize the return value in trap frame.
  2253. st8 [rpT3] = rBSP, TrRsBSPSTORE-TrRsBSP
  2254. (pUser) sub rBSP = rBSP, rBSPStore
  2255. (pUser) mov psr.l = rT3
  2256. ;;
  2257. (pUser) st8 [rpT3] = rBSPStore // save user BSP Store
  2258. (pUser) dep rT2 = rBSP, rT2, RSC_MBZ1, RSC_LOADRS_LEN
  2259. (pUser) mov teb = kteb // get Teb pointer
  2260. movl rT1 = Knsc10 // Leave the EPC page
  2261. ;;
  2262. st8 [rpT2] = rT2, TrRsRNAT-TrRsRSC // save RSC
  2263. (pUser) dep rKBSPStore = rBSPStore, rKBSPStore, 0, 9
  2264. mov bt0 = rT1 // Addres of Knsc10 in KSEG0.
  2265. ;;
  2266. (pUser) mov ar.bspstore = rKBSPStore // switch to kernel BSP
  2267. movl gp = _gp // set up kernel gp
  2268. ;;
  2269. (pUser) mov ar.rnat = rRNAT // preserve uer RNAT bits
  2270. (pUser) st8 [rpT2] = rRNAT // save RNAT in trap frame
  2271. (pUser) mov ar.rsc = RSC_KERNEL // turn rse on, in kernel mode
  2272. (pNatedSp) br.spnt bt1
  2273. br.sptk bt0
  2274. ;;
  2275. //
  2276. // Register aliases for rest of procedure
  2277. //
  2278. #ifdef _CAPKERN
  2279. .regstk 8, 9, 2, 0
  2280. #else
  2281. .regstk 8, 9, 0, 0
  2282. #endif
  2283. rScallGp = loc0
  2284. rpThObj = loc1 // pointer to thread object
  2285. rSavedV0 = loc2 // saved v0 for GUI thread
  2286. rpEntry = loc3 // syscall routine entry point
  2287. rSnumber = loc4 // service number
  2288. rSdOffset = loc5
  2289. rCount = loc6 /* index of the first Nat'ed input register */
  2290. rUserSp = loc7
  2291. rUserPFS = loc8
  2292. //
  2293. // The following code is an out of band error path. Since we always
  2294. // branch between the EPC page to Knsc10 below.
  2295. //
  2296. Knsc_Invalid:
  2297. //
  2298. // If rSdOffset == SERVICE_TABLE_TEST then service number is GUI service
  2299. //
  2300. cmp.ne pInvl, pVal = SERVICE_TABLE_TEST, rSdOffset
  2301. mov v0 = 1
  2302. (pVal) br.call.sptk brp = PsConvertToGuiThread
  2303. ;;
  2304. cmp4.eq pVal, p0 = 0, v0 // pVal = 1, if successful
  2305. movl v0 = STATUS_INVALID_SYSTEM_SERVICE // invalid, if not successful
  2306. ;;
  2307. add rpEntry = @gprel(KeServiceDescriptorTableShadow),gp // Load address of table of shadow table
  2308. // Used by KiSystemServiceRepeat and the
  2309. // fall through case below.
  2310. (pVal) br.sptk KiSystemServiceRepeat // br if successful
  2311. (pInvl) br.spnt Knsc_ErrorReturn // br to KiSystemServiceExit if
  2312. ;; // system call out of range
  2313. //
  2314. // The conversion to a Gui thread failed. The correct return value is encoded
  2315. // in a byte table indexed by the service number that is at the end of the
  2316. // service address table. The encoding is as follows:
  2317. ;;
  2318. //
  2319. // 0 - return 0.
  2320. // -1 - return -1.
  2321. // 1 - return status code.
  2322. //
  2323. add rpT1 = SERVICE_TABLE_TEST, rpEntry // Get addr of the GUI table
  2324. ;;
  2325. ld8 rpT2 = [rpT1], SdLimit - SdBase // Get the table base.
  2326. ;;
  2327. ld4 rT1 = [rpT1] // Get the limit.
  2328. add rpT2 = rpT2, rSnumber // Index by the server number to the correct byte.
  2329. ;;
  2330. shladd rpT2 = rT1, 3, rpT2 // Calculate the end of the table.
  2331. cmp4.ltu pt1, pt0 = rSnumber, rT1 // pt1 = number < limit
  2332. ;; // pt1 == 0 implies return an ntstatus.
  2333. (pt1) ld1 rT1 = [rpT2] // Load the flag byte if within table
  2334. ;;
  2335. sxt1 rT2 = rT1 // Sign extend the result
  2336. (pt1) cmp.eq pt0, pt1 = 1, rT1 // Test for 1 which means return STATUS_INVALID_SYSTEM_SERVICE
  2337. ;;
  2338. (pt1) mov v0 = rT2 // Use the flag value if needed.
  2339. br.sptk Knsc_ErrorReturn // br to KiSystemServiceExit
  2340. ;;
  2341. //
  2342. // Now running with user banked registers and on kernel backing store
  2343. //
  2344. // Can now take TLB faults
  2345. //
  2346. // Preserve the output args (as in's) in the local frame until it's ready to
  2347. // call the specified system service because other calls may have to be made
  2348. // before that. Also allocate locals and one out.
  2349. //
  2350. Knsc10:
  2351. #ifdef _CAPKERN
  2352. alloc rUserPFS = 8, 9, 2, 0
  2353. #else
  2354. alloc rUserPFS = 8, 9, 0, 0
  2355. #endif
  2356. ld8 rpThObj = [rpT4]
  2357. add rpT1 = TrEOFMarker, sp
  2358. ;;
  2359. mov rUserSp = ar.bsp
  2360. movl rT1 = FPSR_FOR_KERNEL // initial fpsr value
  2361. ;;
  2362. mov ar.fpsr = rT1 // set fpsr
  2363. movl rT3 = KTRAP_FRAME_EOF | SYSCALL_FRAME
  2364. ;;
  2365. st8 [rpT1] = rT3, TrNewBSP - TrEOFMarker
  2366. mov rCount = pr // save local predicates
  2367. shladd rUserSp = rIFS, 3, rUserSp
  2368. ;;
  2369. st8 [rpT1] = rUserSp // Save NewBSP.
  2370. mov rSavedV0 = v0 // save syscall # across call
  2371. mov rUserSp = rSp
  2372. add rpT2 = ThServiceTable, rpThObj // Address of thread service table
  2373. add rpT3 = ThTrapFrame, rpThObj
  2374. mov pr = zero, -1
  2375. ;;
  2376. ld8 rT4 = [rpT3], ThPreviousMode-ThTrapFrame
  2377. //
  2378. // the following code uses the predicates to determine the first of
  2379. // the 8 input argument register whose Nat bit is set. The result
  2380. // is saved in register rCount and used to determine whether to fail
  2381. // the system call in Knsc_CheckArguments.
  2382. //
  2383. cmp.eq p1 = r32, r32
  2384. cmp.eq p9 = r33, r33
  2385. cmp.eq p17 = r34, r34
  2386. cmp.eq p25 = r35, r35
  2387. cmp.eq p33 = r36, r36
  2388. cmp.eq p41 = r37, r37
  2389. cmp.eq p49 = r38, r38
  2390. cmp.eq p57 = r39, r39
  2391. ld8 rpEntry = [rpT2] // Load service describtor
  2392. add rpT1 = TrTrapFrame, sp // -> TrTrapFrame
  2393. shr.u rSdOffset = rSavedV0, SERVICE_TABLE_SHIFT // isolate service descriptor offset
  2394. ;;
  2395. ld1 rT0 = [rpT3] // rT0 = thread's previous mode
  2396. st1 [rpT3] = rPreviousMode // set new thread previous mode
  2397. mov rT1 = pr
  2398. ;;
  2399. st8 [rpT1] = rT4, TrPreviousMode-TrTrapFrame
  2400. dep rT1 = 0, rT1, 0, 1 // clear bit 0
  2401. mov pr = rCount, -1 // restore local predicates
  2402. ;;
  2403. and rSdOffset = SERVICE_TABLE_MASK, rSdOffset
  2404. extr.u rSnumber = rSavedV0, 0, 12
  2405. czx1.r rCount = rT1 // determine which arg is Nat'ed
  2406. st4 [rpT1] = rT0
  2407. FAST_ENABLE_INTERRUPTS
  2408. (pKDbg) br.call.spnt brp = KiLoadKernelDebugRegisters
  2409. ;;
  2410. PROLOGUE_END
  2411. //
  2412. // If the specified system service number is not within range, then
  2413. // attempt to convert the thread to a GUI thread and retry the service
  2414. // dispatch.
  2415. //
  2416. // N.B. The system call arguments, the system service entry point (rpEntry),
  2417. // the service number (Snumber)
  2418. // are implicitly preserved in the register stack while attempting to
  2419. // convert the thread to a GUI thread. v0 and the gp must be preserved
  2420. // explicitly.
  2421. //
  2422. // Validate sys call number
  2423. //
  2424. #ifdef _CAPKERN
  2425. br.call.sptk.few b0=_CAP_ThreadID#;;
  2426. #endif
  2427. ALTERNATE_ENTRY(KiSystemServiceRepeat)
  2428. add rpT1 = ThTrapFrame, rpThObj // rpT1 -> ThTrapFrame
  2429. add rpSd = rSdOffset, rpEntry // service descriptor -> rpSd
  2430. cmp4.ne pNoGui, pGui = SERVICE_TABLE_TEST, rSdOffset // check if GUI system service
  2431. ;;
  2432. st8 [rpT1] = sp // set trap frame address
  2433. ld8 rT4 = [rpSd], SdLimit-SdBase // rT4 = table base
  2434. add rpT1 = TeGdiBatchCount, teb
  2435. ;; // We assume SdBase == 0
  2436. #if SdBase
  2437. #error "SdBase not equal zero."
  2438. #endif
  2439. KiSystemServiceTeb::
  2440. ld4 rT1 = [rpSd] // rT1 = table limit
  2441. (pGui) ld4 rT2 = [rpT1] // get number of batched calls
  2442. add rScallGp = -8, rT4 // The GP values is just before the Base
  2443. ;;
  2444. (pGui) cmp4.eq pNoGui, pGui = 0, rT2 // if bacth calls is non-zero then call flush.
  2445. cmp4.ltu pt1, pt0 = rSnumber, rT1 // pt1 = number < limit
  2446. shladd rpT3 = rSnumber, 3, rT4 // -> entry point address
  2447. ;;
  2448. (pt1) ld8 rScallGp = [rScallGp] // load syscall gp
  2449. (pt1) add rpT1 = @gprel(KeGdiFlushUserBatch), gp
  2450. (pt0) br.dpnt Knsc_Invalid // The system call is out of range.
  2451. ;;
  2452. ld8 rpEntry = [rpT3] // -> sys call routine plabel
  2453. (pGui) ld8 rpT1 = [rpT1] // get KeGdiFlushUserBatch()
  2454. (pNoGui) br.dptk Knsc_NotGUI // Not a GUI thread
  2455. ;;
  2456. Knsc_GUI:
  2457. //
  2458. // If the system service is a GUI service and the GDI user batch queue is
  2459. // not empty, then call the appropriate service to flush the user batch.
  2460. //
  2461. ld8 rT1 = [rpT1], PlGlobalPointer-PlEntryPoint // get entry point
  2462. mov rSavedV0 = rpSd // save service descriptor
  2463. ;;
  2464. ld8 gp = [rpT1] // set global pointer
  2465. mov bt0 = rT1
  2466. br.call.sptk brp = bt0 // call to KeGdiFlushUserBatch
  2467. ;;
  2468. #if DBG
  2469. mov rpSd = rSavedV0 // restore service descriptor
  2470. ;;
  2471. #endif
  2472. //
  2473. // Check for Nat'ed input argument register and
  2474. // Copy in-memory arguments from caller stack to kernel stack
  2475. //
  2476. Knsc_NotGUI:
  2477. #ifdef _CAPKERN
  2478. movl out0 = @fptr(KiNormalSystemCall)
  2479. mov out1 = rpEntry
  2480. br.call.sptk.few b0=_CAP_Start_Profiling2
  2481. #endif
  2482. #if DBG // checked build code
  2483. add rpT1 = SdCount-SdLimit, rpSd // rpT1 -> count table address
  2484. ;;
  2485. ld8 rpT2 = [rpT1] // service count table address
  2486. ;;
  2487. cmp.ne pt0 = rpT2, zero // if zero, no table defined
  2488. shladd rpT3 = rSnumber, 2, rpT2 // compute service count address
  2489. ;;
  2490. (pt0) ld4 rT1 = [rpT3] // increment count
  2491. ;;
  2492. (pt0) add rT1 = 1, rT1
  2493. ;;
  2494. (pt0) st4 [rpT3] = rT1 // store result
  2495. #endif // DBG
  2496. and rArgNum = 0xf, rpEntry // extract # of arguments
  2497. and rpEntry = -16, rpEntry // clear least significant 4 bit
  2498. cmp.ne pNatedArg = zero, zero // assume no Nat'ed argument
  2499. mov gp = rScallGp
  2500. movl v0 = STATUS_INVALID_PARAMETER_1
  2501. ;;
  2502. cmp.geu pNoCopy, pCopy = 8, rArgNum // any in-memory arguments ?
  2503. mov bt0 = rpEntry
  2504. mov rSp = rUserSp
  2505. ;;
  2506. add v0 = rCount, v0 // set return status
  2507. dep rPFS = 0, rUserPFS, 62, 2
  2508. add rArgBytes = -8, rArgNum // rArgBytes contion the number of 16 byte chunks to copy.
  2509. ;;
  2510. (pNoCopy) cmp.gt pNatedArg = rArgNum, rCount // any Nat'ed argument ?
  2511. mov ar.pfs = rPFS // Make the user PFS look like our PFS
  2512. (pCopy) cmp.gt pNatedArg = 8, rCount
  2513. ;;
  2514. alloc rT1 = 0,0,8,0 // output regs are ready
  2515. (pNatedArg) br.spnt Knsc_ErrorReturn // exit if Nat'ed arg found
  2516. (pNoCopy) br.sptk KiSystemServiceEnd // skip copy if no memory args
  2517. //
  2518. // Get the caller's sp. If caller was user mode, validate the stack pointer
  2519. // ar.unat contains Nat for previous sp (in TrIntSp)
  2520. //
  2521. (pUser) movl rT2 = MI_USER_PROBE_ADDRESS // User sp limit
  2522. ;;
  2523. add rArgBytes = -1, rArgBytes // decrement count
  2524. (pUser) tnat.nz.unc pt1, pt2 = rSp // test user sp for Nat
  2525. add rpT1 = STACK_SCRATCH_AREA, rSp // adjust previous sp for scratch area
  2526. ;;
  2527. (pt2) cmp.geu pt1 = rSp, rT2 // user sp >= PROBE ADDRESS ?
  2528. add rpT2 = STACK_SCRATCH_AREA, sp // adjust for scratch area
  2529. ;;
  2530. add rpT3 = 8, rpT1 // second source pointer
  2531. add rpT4 = 8, rpT2 // second destination pointer
  2532. (pt1) mov rpT1 = rT2 // set out of range (includes Nat case)
  2533. ;;
  2534. //
  2535. // At this point rpT1, rpT3 -> source and rpT2, rpT4 -> destination
  2536. // Copy rArgBytes from source to destination, 16 bytes per iteration
  2537. // Exceptions handled by KiSystemServiceHandler
  2538. //
  2539. KiSystemServiceStart::
  2540. Knsc_CopyLoop:
  2541. ld8 rT1 = [rpT1], 16 // get caller arg
  2542. ld8 rT2 = [rpT3], 16 // get caller arg
  2543. cmp4.gt pt1 = rArgBytes, zero // loop if # bytes > 0
  2544. ;;
  2545. nop.m 0
  2546. nop.f 0
  2547. add rArgBytes = -1, rArgBytes // decrement count
  2548. st8 [rpT2] = rT1, 16 // store in kernel stack
  2549. st8 [rpT4] = rT2, 16 // store in kernel stack
  2550. (pt1) br.dpnt Knsc_CopyLoop
  2551. ;;
  2552. KiSystemServiceEnd::
  2553. //
  2554. // N.B. t0 is reserved to pass trap frame address to NtContinue()
  2555. //
  2556. mov t0 = sp // for NtContinue()
  2557. movl rT1 = KiSystemServiceExit
  2558. ;;
  2559. //
  2560. // This is not call since that would change the stack registers.
  2561. // we want to got to the routine with the same argument regisers
  2562. // that we entered with.
  2563. //
  2564. mov brp = rT1
  2565. br.sptk bt0 // call routine(args)
  2566. ;;
  2567. KiSystemServiceExit::
  2568. //
  2569. // make the current bsp the same as the saved BSP in the trap frame
  2570. //
  2571. add rpT2 = TrStIPSR, sp
  2572. cover
  2573. ;;
  2574. #ifdef _CAPKERN
  2575. alloc rT1 = ar.pfs, 0, 0, 1, 0
  2576. movl gp = _gp // restore to kernel GP value
  2577. ;;
  2578. CAPEND(KiNormalSystemCall)
  2579. br.call.sptk.few b0=_CAP_SetCPU#
  2580. ;;
  2581. add rpT2 = TrStIPSR, sp
  2582. ;;
  2583. #endif
  2584. //
  2585. // At this point:
  2586. // ar.unat contains Nat for previous sp (ar.unat is preserved register)
  2587. // sp -> trap frame
  2588. //
  2589. // Returning from "call": no need to restore volatile state
  2590. // *** TBD *** : zero volatile state for security? PPC does zero, mips does not.
  2591. //
  2592. //
  2593. // Update PbSystemCalls
  2594. //
  2595. //
  2596. // Restore thread previous mode and trap frame address from the trap frame
  2597. //
  2598. lfetch [rpT2], TrTrapFrame-TrStIPSR
  2599. movl rpT1 = KiPcr + PcPrcb // rpT1 -> Prcb
  2600. ;;
  2601. ld8 rT2 = [rpT2], TrPreviousMode-TrTrapFrame
  2602. ld8 rpT3 = [rpT1], PcCurrentThread-PcPrcb
  2603. ;;
  2604. FAST_DISABLE_INTERRUPTS
  2605. ld8 rThread = [rpT1] // rpT1 -> current thread
  2606. add rpT3 = PbSystemCalls, rpT3 // pointer to sys call counter
  2607. ;;
  2608. ld4 rT1 = [rpT3] // rT1.4 = counter value
  2609. ld4 rT3 = [rpT2], TrRsRSC-TrPreviousMode
  2610. add rpT4 = ThTrapFrame, rThread // -> thread trap frame
  2611. add rpT1 = ThApcState+AsUserApcPending, rThread
  2612. ;;
  2613. (pKrnl) ld8 rRscE = [rpT2] // load user RSC
  2614. (pUser) ld1 rT4 = [rpT1], ThAlerted - ThApcState - AsUserApcPending
  2615. add rT1 = 1, rT1 // increment
  2616. ;;
  2617. st8 [rpT4] = rT2, ThPreviousMode-ThTrapFrame
  2618. st4 [rpT3] = rT1 // store
  2619. ;;
  2620. st1 [rpT4] = rT3 // restore prevmode in thread
  2621. mov t0 = sp // set t0 to trap frame
  2622. (pKrnl) br.spnt Knsc_CommonExit // br if returning to kernel
  2623. ;;
  2624. st1 [rpT1] = zero
  2625. cmp4.eq pt0 = zero, rT4
  2626. (pt0) br.sptk KiUserServiceExit
  2627. ;;
  2628. alloc rT1 = ar.pfs, 0, 1, 2, 0
  2629. add loc0 = TrIntV0, sp
  2630. add rpT1 = TrIntTeb, sp
  2631. //
  2632. // v0 is saved in the trap frame so the return status can be restored
  2633. // by NtContinue after the user APC has been dispatched.
  2634. //
  2635. ssm 1 << PSR_I // enable interrupts
  2636. mov rT3 = APC_LEVEL
  2637. ;;
  2638. SET_IRQL (rT3)
  2639. ;;
  2640. st8.nta [loc0] = v0 // save return status in trap frame
  2641. movl gp = _gp // restore to kernel gp value
  2642. st8.nta [rpT1] = teb
  2643. #ifdef _CAPKERN
  2644. mov rpT1 = out0
  2645. ;;
  2646. CAPSTART(KiNormalSystemCall,KiApcInterrupt)
  2647. mov out0 = rpT1
  2648. #endif
  2649. mov out1 = sp
  2650. br.call.sptk brp = KiApcInterrupt
  2651. ;;
  2652. CAPEND(KiNormalSystemCall)
  2653. rsm 1 << PSR_I // disable interrupt
  2654. ld8.nta v0 = [loc0] // restore system call return status
  2655. SET_IRQL (zero)
  2656. HANDLER_EXIT(KiNormalSystemCall)
  2657. //
  2658. // KiServiceExit is carefully constructed as a continuation of
  2659. // KiNormalSystemCall. From now on, t0 must be preserved because it is
  2660. // used to hold the trap frame address. v0 must be preserved because it
  2661. // is holding the return status.
  2662. // This section of code is also written to overwrite the tempoary interger
  2663. // registers so that no information is leaked back to the user.
  2664. //
  2665. HANDLER_ENTRY_EX(KiServiceExit, KiSystemServiceHandler)
  2666. .prologue
  2667. .unwabi @nt, EXCEPTION_FRAME
  2668. .vframe t0
  2669. mov t0 = sp
  2670. ;;
  2671. ALTERNATE_ENTRY(KiUserServiceExit)
  2672. (pUser) add rpT3 = TrStIPSR, t0
  2673. ;;
  2674. (pUser) ld8 rpT3 = [rpT3]
  2675. invala
  2676. ;;
  2677. (pUser) tbit.nz.unc pUDbg = rpT3, PSR_DB // if user psr.db set, load user DRs
  2678. (pUDbg) br.call.spnt brp = KiLoadUserDebugRegisters
  2679. ;;
  2680. add rpT1 = TrRsRSC, t0 // -> user RSC
  2681. add rpT2 = TrRsBSP, t0 // -> user BSP Store
  2682. ;;
  2683. PROLOGUE_END
  2684. ld8 rRscE = [rpT1], TrRsRNAT-TrRsRSC // load user RSC
  2685. ld8 rBSP = [rpT2]
  2686. mov rRscD = RSC_KERNEL_DISABLED
  2687. ;;
  2688. //
  2689. // Switch to user BSP -- put in load intensive mode to overlap RS restore
  2690. // with volatile state restore.
  2691. //
  2692. ld8 rRNAT = [rpT1] // user RNAT
  2693. extr.u rRscDelta = rRscE, RSC_MBZ1, RSC_LOADRS_LEN
  2694. dep rRscE = r0, rRscE, RSC_MBZ1, RSC_LOADRS_LEN
  2695. movl rpT1 = KiIA64RseNumOfMaxDirty
  2696. ;;
  2697. .regstk 0, 0, 1, 0
  2698. alloc rT2 = 0,0,1,0
  2699. ld8 rpT1 = [rpT1]
  2700. dep rRscD = rRscDelta, rRscD, RSC_LOADRS, RSC_LOADRS_LEN
  2701. sub rBSPStore = rBSP, rRscDelta
  2702. shr.u out0 = rRscDelta, 3
  2703. ;;
  2704. cmp.gt pt0 = rpT1, out0
  2705. sub out0 = rpT1, out0
  2706. (pt0) br.call.sptk brp = KeScrubBackingStoreRegisters
  2707. ;;
  2708. alloc rT2 = 0, 0, 0, 0
  2709. mov ar.rsc = rRscD // turn off RSE
  2710. ;;
  2711. loadrs // pull in user regs
  2712. ;;
  2713. mov ar.bspstore = rBSPStore // restore user BSP
  2714. ;;
  2715. mov ar.rnat = rRNAT // restore user RNAT
  2716. Knsc_CommonExit:
  2717. add rpT1 = TrIntSp, t0
  2718. movl rpT2 = KiPcr+PcCurrentThread
  2719. add rpT4 = TrStIPSR, t0
  2720. add rpT3 = TrStIIP, t0
  2721. ;;
  2722. ld8 rSp = [rpT1], TrPreds-TrIntSp
  2723. .pred.rel "mutex",pUser,pKrnl
  2724. (pUser) ld8 rT1 = [rpT2], PcHighFpOwner-PcCurrentThread
  2725. (pKrnl) add rpT2 = PcKernelDebugActive-PcCurrentThread, rpT2
  2726. ;;
  2727. ld8 rIPSR = [rpT4], TrStIFS-TrStIPSR
  2728. (pUser) ld8 rT2 = [rpT2]
  2729. (pKrnl) mov rPreviousMode = KernelMode
  2730. ;;
  2731. ld8 rIIP = [rpT3], TrStFPSR-TrStIIP
  2732. (pKrnl) ld1 rT2 = [rpT2]
  2733. (pUser) mov rPreviousMode = UserMode
  2734. ;;
  2735. mov ar.rsc = rRscE // restore RSC
  2736. (pUser) cmp.ne.unc pt0 = rT1, rT2
  2737. ;;
  2738. ld8 rT3 = [rpT3] // load fpsr
  2739. ld8 rIFS = [rpT4] // load IFS
  2740. (pt0) dep rIPSR = 1, rIPSR, PSR_DFH, 1
  2741. ;;
  2742. (pKrnl) cmp.ne.unc pKDbg, pt2 = rT2, r0 // hardware debug active?
  2743. dep rIPSR = 0, rIPSR, PSR_MFH, 1 // psr.mfh
  2744. ;;
  2745. ld8 rPreds = [rpT1], TrApUNAT-TrPreds
  2746. (pt2) dep rIPSR = 0, rIPSR, PSR_DB, 1 // disable db in kernel
  2747. (pKDbg) dep rIPSR = 1, rIPSR, PSR_DB, 1 // enable db in kernel
  2748. ;;
  2749. ld8 rUNAT = [rpT1]
  2750. mov t11 = r0 // Sanitize
  2751. mov pr = rPreds // restore preds
  2752. ;;
  2753. mov ar.csd = r0 // Sanitize CSD
  2754. rsm 1 << PSR_IC // disable PSR.ic
  2755. mov ar.unat = rUNAT // restore UNAT
  2756. ;;
  2757. srlz.d // must serialize
  2758. mov ar.fpsr = rT3 // restore FPSR
  2759. ;;
  2760. //
  2761. // The system return case must be handle separately from the user return
  2762. // case, so we can determine which stack we are currently using in case
  2763. // a trap is take before we can return.
  2764. //
  2765. mov sp = rSp
  2766. //
  2767. // Restore status registers
  2768. //
  2769. mov cr.ipsr = rIPSR // restore previous IPSR
  2770. mov cr.ifs = rIFS // restore previous IFS
  2771. mov cr.iip = rIIP // restore previous IIP
  2772. ;;
  2773. //
  2774. // Resume at point of interruption (rfi must be at end of instruction group)
  2775. //
  2776. rfi
  2777. ;;
  2778. Knsc_ErrorReturn:
  2779. //
  2780. // N.B. t0 is reserved to pass trap frame address to NtContinue()
  2781. //
  2782. add rPFS = TrRsPFS, sp
  2783. ;;
  2784. ld8 rPFS = [rPFS]
  2785. ;;
  2786. dep rPFS = 0, rPFS, 62, 2
  2787. ;;
  2788. mov ar.pfs = rPFS
  2789. movl rT1 = KiSystemServiceExit
  2790. ;;
  2791. mov brp = rT1
  2792. br.ret.sptk brp
  2793. ;;
  2794. HANDLER_EXIT(KiServiceExit)
  2795. .text
  2796. //++
  2797. //--------------------------------------------------------------------
  2798. // Routine:
  2799. //
  2800. // KiGenericExceptionHandler
  2801. //
  2802. // Description:
  2803. //
  2804. // First level handler for heavyweight exceptions.
  2805. //
  2806. // On entry:
  2807. //
  2808. // ic off
  2809. // interrupts disabled
  2810. // current frame covered
  2811. // rHIFA must be initialized to a non-nated value
  2812. //
  2813. // Process:
  2814. //
  2815. // Notes:
  2816. //
  2817. // PCR page mapped with TR
  2818. //--------------------------------------------------------------------
  2819. HANDLER_ENTRY(KiGenericExceptionHandler)
  2820. .prologue
  2821. .unwabi @nt, EXCEPTION_FRAME
  2822. ALLOCATE_TRAP_FRAME
  2823. //
  2824. // sp points to trap frame
  2825. //
  2826. // Save exception handler routine in kernel register
  2827. //
  2828. mov rkHandler = rHHandler
  2829. movl rTH3 = KiPcr+PcSavedIFA
  2830. ;;
  2831. st8 [rTH3] = rHIFA
  2832. //
  2833. // Save interruption state in trap frame and switch to user bank registers
  2834. // and switch to kernel backing store.
  2835. //
  2836. SAVE_INTERRUPTION_STATE
  2837. //
  2838. // Now running with user banked registers and on kernel stack.
  2839. //
  2840. // Can now take TLB faults
  2841. //
  2842. // sp -> trap frame
  2843. //
  2844. br.call.sptk brp = KiSaveTrapFrame
  2845. ;;
  2846. //
  2847. // Register aliases
  2848. //
  2849. rpT1 = t0
  2850. rpT2 = t1
  2851. rpT3 = t2
  2852. rT1 = t3
  2853. rT2 = t4
  2854. rT3 = t5
  2855. rPreviousMode = t6 // previous mode
  2856. rT4 = t7
  2857. mov rT1 = rkHandler // restore address of interruption routine
  2858. movl rpT1 = KiPcr+PcSavedIIM
  2859. ;;
  2860. ld8 rT2 = [rpT1], PcSavedIFA-PcSavedIIM // load saved IIM
  2861. add rpT2 = TrEOFMarker, sp
  2862. add rpT3 = TrStIIM, sp
  2863. ;;
  2864. ld8 rT4 = [rpT1] // load saved IFA
  2865. movl rT3 = KTRAP_FRAME_EOF | EXCEPTION_FRAME
  2866. ;;
  2867. mov t8 = ar.bsp
  2868. st8 [rpT2] = rT3, TrNewBSP-TrEOFMarker
  2869. st8 [rpT3] = rT2, TrStIFA-TrStIIM // save IIM in trap frame
  2870. ;;
  2871. .regstk 0, 1, 2, 0 // must match KiExceptionExit
  2872. alloc out1 = 0,1,2,0
  2873. st8 [rpT3] = rT4 // save IFA in trap frame
  2874. mov bt0 = rT1 // set destination address
  2875. PROLOGUE_END
  2876. //
  2877. // Dispatch the exception via call to address in rkHandler
  2878. //
  2879. .pred.rel "mutex",pUser,pKrnl
  2880. add rpT1 = TrPreviousMode, sp // -> previous mode
  2881. (pUser) mov rPreviousMode = UserMode // set previous mode
  2882. (pKrnl) mov rPreviousMode = KernelMode
  2883. ;;
  2884. st4 [rpT1] = rPreviousMode // save in trap frame
  2885. st8 [rpT2] = t8 // Save new BSP for debugging
  2886. (pKDbg) br.call.spnt brp = KiLoadKernelDebugRegisters
  2887. ;;
  2888. FAST_ENABLE_INTERRUPTS // enable interrupt
  2889. mov out0 = sp // trap frame pointer
  2890. br.call.sptk brp = bt0 // call handler(tf) (C code)
  2891. ;;
  2892. .pred.rel "mutex",pUser,pKrnl
  2893. cmp.ne pt0, pt1 = v0, zero
  2894. (pUser) mov out1 = UserMode
  2895. (pKrnl) mov out1 = KernelMode
  2896. //
  2897. // does not return
  2898. //
  2899. mov out0 = sp
  2900. (pt1) br.cond.sptk KiAlternateExit
  2901. (pt0) br.call.spnt brp = KiExceptionDispatch
  2902. ;;
  2903. //
  2904. // Interrupts need to be disable be for mess up the stack such that
  2905. // the unwind code does not work.
  2906. //
  2907. FAST_DISABLE_INTERRUPTS
  2908. ;;
  2909. ALTERNATE_ENTRY(KiExceptionExit)
  2910. //++
  2911. //
  2912. // Routine Description:
  2913. //
  2914. // This routine is called to exit from an exception.
  2915. //
  2916. // N.B. This transfer of control occurs from:
  2917. //
  2918. // 1. fall-through from above
  2919. // 2. exit from continue system service
  2920. // 3. exit from raise exception system service
  2921. // 4. exit into user mode from thread startup
  2922. //
  2923. // Arguments:
  2924. //
  2925. // loc0 - pointer to trap frame
  2926. // sp - pointer to high preserved float save area + STACK_SCRATCH_AREA
  2927. //
  2928. // Return Value:
  2929. //
  2930. // Does not return.
  2931. //
  2932. //--
  2933. //
  2934. // upon entry of this block, s0 and s1 must be set to the address of
  2935. // the trap and the exception frames respectively.
  2936. //
  2937. // preserved state is restored here because they may have been modified
  2938. // by SetContext
  2939. //
  2940. LEAF_SETUP(0, 1, 2, 0) // must be in sync with
  2941. // KiGenericExceptionHandler
  2942. mov loc0 = s0 // -> trap frame
  2943. mov out0 = s1 // -> exception frame
  2944. ;;
  2945. br.call.sptk brp = KiRestoreExceptionFrame
  2946. ;;
  2947. mov sp = loc0 // deallocate exception
  2948. // frame by restoring sp
  2949. ALTERNATE_ENTRY(KiAlternateExit)
  2950. //
  2951. // sp -> trap frame addres
  2952. //
  2953. // Interrupts disabled from here to rfi
  2954. //
  2955. FAST_DISABLE_INTERRUPTS
  2956. ;;
  2957. RETURN_FROM_INTERRUPTION(Ked)
  2958. //
  2959. // Add four nop cycles (two bundles) bundles of NOP's to
  2960. // workaround McKinly Errata.
  2961. //
  2962. nop.m 0
  2963. ;;
  2964. nop.m 0
  2965. ;;
  2966. nop.m 0
  2967. ;;
  2968. nop.m 0
  2969. ;;
  2970. HANDLER_EXIT(KiGenericExceptionHandler)
  2971. //--------------------------------------------------------------------
  2972. // Routine:
  2973. //
  2974. // KiExternalInterruptHandler
  2975. //
  2976. // Description:
  2977. //
  2978. // First level external interrupt handler. Dispatch highest priority
  2979. // pending interrupt.
  2980. //
  2981. // On entry:
  2982. //
  2983. // ic off
  2984. // interrupts disabled
  2985. // current frame covered
  2986. //
  2987. // Process:
  2988. //--------------------------------------------------------------------
  2989. HANDLER_ENTRY(KiExternalInterruptHandler)
  2990. //
  2991. // Now running with user banked registers and on kernel backing store.
  2992. // N.B. sp -> trap frame
  2993. //
  2994. // Can now take TLB faults
  2995. //
  2996. .prologue
  2997. .unwabi @nt, INTERRUPT_FRAME
  2998. .regstk 0, 4, 2, 0
  2999. alloc loc0 = 0, 4, 2, 0
  3000. //
  3001. // Register aliases
  3002. //
  3003. rVector = loc0
  3004. rSaveGP = loc1
  3005. rpSaveIrql = loc2 // -> old irql in trap frame
  3006. rOldIrql = loc3
  3007. rpT1 = t0
  3008. rpT2 = t1
  3009. rpT3 = t2
  3010. rT1 = t3
  3011. rT2 = t4
  3012. rT3 = t5
  3013. rPreviousMode = t6 // previous mode
  3014. rNewIrql = t7
  3015. pEOI = pt1
  3016. movl rOldIrql = KiPcr+PcCurrentIrql
  3017. ;;
  3018. //
  3019. // Save kernel gp
  3020. //
  3021. mov rSaveGP = gp
  3022. //
  3023. // Get the vector number
  3024. //
  3025. mov rVector = cr.ivr // for A0 2173 workaround
  3026. br.call.sptk brp = KiSaveTrapFrame
  3027. ;;
  3028. #if defined(INTERRUPTION_LOGGING)
  3029. movl t0 = KiVectorLogMask
  3030. ;;
  3031. ld8 t1 = [t0]
  3032. ;;
  3033. tbit.z pt1 = t1, ExternalInterruptBit
  3034. (pt1) br.cond.sptk EndOfLogging2
  3035. movl t0 = KiPcr+PcInterruptionCount
  3036. ;;
  3037. ld4.nt1 t0 = [t0]
  3038. mov t1 = MAX_NUMBER_OF_IHISTORY_RECORDS - 1
  3039. ;;
  3040. add t0 = -1, t0
  3041. movl t2 = KiPcr+0x1000
  3042. ;;
  3043. and t1 = t0, t1
  3044. ;;
  3045. shl t1 = t1, 5
  3046. ;;
  3047. add t0 = t2, t1
  3048. ;;
  3049. add t0 = 24, t0
  3050. ;;
  3051. st8.nta [t0] = rVector // save ivr in the Extra0 field
  3052. // For Conditional Interrupt Logging
  3053. EndOfLogging2:
  3054. #endif // defined(INTERRUPTION_LOGGING)
  3055. //
  3056. // Exit if spurious interrupt vector
  3057. //
  3058. cmp.eq pt0, pt1 = 0xF, rVector
  3059. ld1 rOldIrql = [rOldIrql] // The Irql in the PCR has been santized in
  3060. // SAVE_INTERRUPTION_STATE.
  3061. (pt0) br.spnt Keih_Exit
  3062. ;;
  3063. //
  3064. // sp -> trap frame
  3065. //
  3066. add rpSaveIrql = TrEOFMarker, sp
  3067. movl rT3 = KTRAP_FRAME_EOF | INTERRUPT_FRAME
  3068. ;;
  3069. st8 [rpSaveIrql] = rT3, TrPreviousMode - TrEOFMarker
  3070. .pred.rel "mutex",pUser,pKrnl
  3071. (pUser) mov rPreviousMode = UserMode // set previous mode
  3072. (pKrnl) mov rPreviousMode = KernelMode
  3073. ;;
  3074. st4 [rpSaveIrql] = rPreviousMode, TrOldIrql-TrPreviousMode
  3075. ;;
  3076. st4 [rpSaveIrql] = rOldIrql // save irql in trap frame
  3077. (pKDbg) br.call.spnt brp = KiLoadKernelDebugRegisters
  3078. ;;
  3079. PROLOGUE_END
  3080. Keih_InterruptLoop:
  3081. //
  3082. // Dispatch the interrupt: first raise the IRQL to the level of the new
  3083. // interrupt and enable interrupts.
  3084. //
  3085. GET_IRQL_FOR_VECTOR(p0, rNewIrql, rVector)
  3086. movl rpT3 = KiPcr+PcInterruptRoutine // -> interrupt routine table
  3087. ;;
  3088. shladd rpT3 = rVector, INT_ROUTINES_SHIFT, rpT3 // base + offset
  3089. SET_IRQL (rNewIrql) // raise to new level
  3090. movl rpT1 = KiPcr + PcPrcb // pointer to prcb
  3091. ;;
  3092. ld8 out0 = [rpT3] // out0 -> interrupt dispatcher
  3093. ld8 rpT1 = [rpT1]
  3094. mov out1 = sp // out1 -> trap frame
  3095. ;;
  3096. FAST_ENABLE_INTERRUPTS
  3097. add rpT1 = PbInterruptCount, rpT1 // -> interrupt counter
  3098. ;;
  3099. ld4.nta rT1 = [rpT1] // counter value
  3100. ld8.nta rT2 = [out0], PlGlobalPointer-PlEntryPoint // get entry point
  3101. ;;
  3102. add rT1 = 1, rT1 // increment
  3103. ;;
  3104. //
  3105. // Call the interrupt dispatch routine via a function pointer
  3106. //
  3107. st4.nta [rpT1] = rT1 // store, ignore overflow
  3108. ;;
  3109. ld8.nta gp = [out0], PlEntryPoint-PlGlobalPointer
  3110. mov bt0 = rT2
  3111. br.call.sptk brp = bt0 // call ISR
  3112. ;;
  3113. ld4 rOldIrql = [rpSaveIrql]
  3114. mov gp = rSaveGP
  3115. END_OF_INTERRUPT // end of interrupt processing
  3116. IO_END_OF_INTERRUPT(rVector,rT1,rT2,pEOI)
  3117. ;;
  3118. srlz.d
  3119. //
  3120. // Disable interrupts and restore IRQL level
  3121. //
  3122. FAST_DISABLE_INTERRUPTS
  3123. cmp.gt pt0 = APC_LEVEL, rOldIrql
  3124. mov t0 = APC_LEVEL
  3125. ;;
  3126. (pt0) br.spnt ke_call_apc
  3127. ke_call_apc_resume:
  3128. LOWER_IRQL (rOldIrql)
  3129. //
  3130. // Get the next vector number
  3131. //
  3132. mov rVector = cr.ivr // for A0 2173 workaround
  3133. ;;
  3134. //
  3135. // Loop if more interrupts pending (spurious vector == 0xF)
  3136. //
  3137. cmp.ne pt0 = 0xF, rVector
  3138. ;;
  3139. (pt0) br.spnt Keih_InterruptLoop
  3140. br.sptk Keih_Exit
  3141. ;;
  3142. ke_call_apc:
  3143. LOWER_IRQL (t0)
  3144. ke_call_apc1:
  3145. movl t0 = KiPcr+PcApcInterrupt
  3146. ;;
  3147. ld1 t1 = [t0]
  3148. st1 [t0] = r0
  3149. ;;
  3150. cmp.eq pt0 = r0, t1
  3151. ;;
  3152. (pt0) br.sptk ke_call_apc_resume
  3153. FAST_ENABLE_INTERRUPTS
  3154. mov out1 = sp
  3155. br.call.sptk brp = KiApcInterrupt
  3156. FAST_DISABLE_INTERRUPTS
  3157. br.sptk ke_call_apc1
  3158. Keih_Exit:
  3159. RETURN_FROM_INTERRUPTION(Keih)
  3160. HANDLER_EXIT(KiExternalInterruptHandler)
  3161. //--------------------------------------------------------------------
  3162. // Routine:
  3163. //
  3164. // KiPanicHandler
  3165. //
  3166. // Description:
  3167. //
  3168. // Handler for panic. Call the bug check routine. A place
  3169. // holder for now.
  3170. //
  3171. // On entry:
  3172. //
  3173. // running on kernel memory stack and kernel backing store
  3174. // sp: top of stack -- points to trap frame
  3175. // interrupts enabled
  3176. //
  3177. // IIP: address of bundle causing fault
  3178. //
  3179. // IPSR: copy of PSR at time of interruption
  3180. //
  3181. // Output:
  3182. //
  3183. // sp: top of stack -- points to trap frame
  3184. //
  3185. // Return value:
  3186. //
  3187. // none
  3188. //
  3189. // Notes:
  3190. //
  3191. // If ISR code out of bounds, this code will inovke the panic handler
  3192. //
  3193. //--------------------------------------------------------------------
  3194. HANDLER_ENTRY(KiPanicHandler)
  3195. .prologue
  3196. .unwabi @nt, EXCEPTION_FRAME
  3197. mov ar.k1 = rTH1 // Save Old Stack Limit
  3198. mov ar.k2 = rTH2 // Save Old BSP Limit
  3199. mov ar.k4 = rHVector
  3200. mov rkHandler = rHHandler
  3201. ;;
  3202. mov rHpT1 = KERNEL_STACK_SIZE
  3203. movl rTH1 = KiPcr+PcPanicStack
  3204. ;;
  3205. ld8 sp = [rTH1], PcInitialStack-PcPanicStack
  3206. movl rTH2 = KiPcr+PcSystemReserved
  3207. ;;
  3208. st4 [rTH2] = rPanicCode
  3209. st8 [rTH1] = sp, PcStackLimit-PcInitialStack
  3210. sub rTH2 = sp, rHpT1
  3211. ;;
  3212. st8 [rTH1] = rTH2, PcInitialBStore-PcStackLimit
  3213. mov rHpT1 = KERNEL_BSTORE_SIZE
  3214. ;;
  3215. st8 [rTH1] = sp, PcBStoreLimit-PcInitialBStore
  3216. add rTH2 = rHpT1, sp
  3217. add sp = -TrapFrameLength, sp
  3218. ;;
  3219. st8 [rTH1] = rTH2, PcSavedIFA - PcBStoreLimit
  3220. ;;
  3221. st8 [rTH1] = rHIFA, PcSavedIIM - PcSavedIFA
  3222. mov rTH2 = cr.iha
  3223. ;;
  3224. st8 [rTH1] = rTH2 // save iha in the iim field
  3225. SAVE_INTERRUPTION_STATE
  3226. //
  3227. // switch to kernel back
  3228. //
  3229. bsw.0
  3230. ;;
  3231. rpRNAT = h16
  3232. rpBSPStore= h17
  3233. rBSPStore = h18
  3234. rKBSPStore= h19
  3235. rRNAT = h20
  3236. rKrnlFPSR = h21
  3237. mov ar.rsc = r0 // put RSE in lazy mode
  3238. movl rKBSPStore = KiPcr+PcInitialBStore
  3239. ;;
  3240. mov rBSPStore = ar.bspstore
  3241. mov rRNAT = ar.rnat
  3242. ;;
  3243. ld8 rKBSPStore = [rKBSPStore]
  3244. add rpRNAT = TrRsRNAT, sp
  3245. add rpBSPStore = TrRsBSPSTORE, sp
  3246. ;;
  3247. st8 [rpRNAT] = rRNAT
  3248. st8 [rpBSPStore] = rBSPStore
  3249. dep rKBSPStore = rBSPStore, rKBSPStore, 0, 9
  3250. ;;
  3251. mov ar.bspstore = rKBSPStore
  3252. mov ar.rsc = RSC_KERNEL
  3253. ;;
  3254. //
  3255. // switch to user bank
  3256. //
  3257. bsw.1
  3258. ;;
  3259. alloc out0 = ar.pfs, 0, 0, 5, 0
  3260. ;;
  3261. PROLOGUE_END
  3262. br.call.sptk brp = KiSaveTrapFrame
  3263. ;;
  3264. movl rpT1 = KiPcr+PcSavedIIM
  3265. ;;
  3266. ld8 rT2 = [rpT1], PcSavedIFA-PcSavedIIM // load iha
  3267. ;;
  3268. ld8 rT3 = [rpT1] // load ifa
  3269. add rpT3 = TrStIHA, sp
  3270. ;;
  3271. st8 [rpT3] = rT2, TrStIFA-TrStIHA
  3272. ;;
  3273. st8 [rpT3] = rT3
  3274. // Raise the IRQL to HIGH
  3275. add rpT2 = TrOldIrql, sp
  3276. movl rpT1 = KiPcr + PcCurrentIrql
  3277. ;;
  3278. ld1 rT1 = [rpT1]
  3279. mov rT2 = HIGH_LEVEL
  3280. ;;
  3281. st1 [rpT2] = rT1
  3282. st1 [rpT1] = rT2
  3283. dep.z rT3 = rT2, TPR_MIC, TPR_MIC_LEN
  3284. ;;
  3285. mov cr.tpr = rT3
  3286. mov out2 = ar.k4 // 3rd argument: caller of panic
  3287. mov out3 = rkHandler
  3288. movl out0 = KiPcr+PcSystemReserved
  3289. ;;
  3290. ld4 out0 = [out0] // 1st argument: panic code
  3291. mov out1 = sp // 2nd argument: trap frame
  3292. br.call.sptk.many brp = KeBugCheckEx
  3293. ;;
  3294. nop.m 0
  3295. nop.m 0
  3296. nop.i 0
  3297. ;;
  3298. HANDLER_EXIT(KiPanicHandler)
  3299. //++
  3300. //--------------------------------------------------------------------
  3301. // Routine:
  3302. //
  3303. // VOID
  3304. // KiSaveTrapFrame(PKTRAP_FRAME)
  3305. //
  3306. // Description:
  3307. //
  3308. // Save volatile application state in trap frame.
  3309. // Note: sp, brp, UNAT, RSC, predicates, BSP, BSP Store,
  3310. // PFS, CSD, and FPSR saved elsewhere.
  3311. //
  3312. // Input:
  3313. //
  3314. // sp: points to trap frame
  3315. // ar.unat: contains the Nats of sp, gp, teb, which have already
  3316. // been spilled into the trap frame.
  3317. //
  3318. // Output:
  3319. //
  3320. // None
  3321. //
  3322. // Return value:
  3323. //
  3324. // none
  3325. //
  3326. //--------------------------------------------------------------------
  3327. LEAF_ENTRY(KiSaveTrapFrame)
  3328. .regstk 0, 3, 0, 0
  3329. //
  3330. // Local register aliases
  3331. //
  3332. rpTF1 = loc0
  3333. rpTF2 = loc1
  3334. rL1 = t0
  3335. rL2 = t1
  3336. rL3 = t2
  3337. rL4 = t3
  3338. rL5 = t4
  3339. //
  3340. // (ar.unat unchanged from point of save)
  3341. // Spill temporary (volatile) integer registers
  3342. //
  3343. alloc loc2 = 0,3,0,0 // don't destroy static register
  3344. add rpTF1 = TrIntT0, sp // -> t0 save area
  3345. add rpTF2 = TrIntT1, sp // -> t1 save area
  3346. ;;
  3347. .mem.offset 0,0
  3348. st8.spill [rpTF1] = t0, TrIntT2-TrIntT0 // spill t0 - t22
  3349. .mem.offset 8,0
  3350. st8.spill [rpTF2] = t1, TrIntT3-TrIntT1
  3351. ;;
  3352. .mem.offset 0,0
  3353. st8.spill [rpTF1] = t2, TrIntT4-TrIntT2
  3354. .mem.offset 8,0
  3355. st8.spill [rpTF2] = t3, TrIntT5-TrIntT3
  3356. ;;
  3357. .mem.offset 0,0
  3358. st8.spill [rpTF1] = t4, TrIntT6-TrIntT4
  3359. .mem.offset 8,0
  3360. st8.spill [rpTF2] = t5, TrIntT7-TrIntT5
  3361. mov rL2 = bt0
  3362. ;;
  3363. mov rL1 = ar.csd
  3364. mov rL4 = ar.ccv
  3365. mov rL3 = bt1
  3366. ;;
  3367. .mem.offset 0,0
  3368. st8.spill [rpTF1] = t6, TrIntT8-TrIntT6
  3369. .mem.offset 8,0
  3370. st8.spill [rpTF2] = t7, TrIntT9-TrIntT7
  3371. mov t5 = cr.tpr // Capture the real IRQL
  3372. ;;
  3373. .mem.offset 0,0
  3374. st8.spill [rpTF1] = t8, TrIntT10-TrIntT8
  3375. .mem.offset 8,0
  3376. st8.spill [rpTF2] = t9, TrIntT11-TrIntT9
  3377. ;;
  3378. .mem.offset 0,0
  3379. st8.spill [rpTF1] = t10, TrIntT12-TrIntT10
  3380. .mem.offset 8,0
  3381. st8.spill [rpTF2] = t11, TrIntT13-TrIntT11
  3382. ;;
  3383. .mem.offset 0,0
  3384. st8.spill [rpTF1] = t12, TrIntT14-TrIntT12
  3385. .mem.offset 8,0
  3386. st8.spill [rpTF2] = t13, TrIntT15-TrIntT13
  3387. ;;
  3388. .mem.offset 0,0
  3389. st8.spill [rpTF1] = t14, TrIntT16-TrIntT14
  3390. .mem.offset 8,0
  3391. st8.spill [rpTF2] = t15, TrIntT17-TrIntT15
  3392. ;;
  3393. .mem.offset 0,0
  3394. st8.spill [rpTF1] = t16, TrIntT18-TrIntT16
  3395. .mem.offset 8,0
  3396. st8.spill [rpTF2] = t17, TrIntT19-TrIntT17
  3397. ;;
  3398. .mem.offset 0,0
  3399. st8.spill [rpTF1] = t18, TrIntT20-TrIntT18
  3400. .mem.offset 8,0
  3401. st8.spill [rpTF2] = t19, TrIntT21-TrIntT19
  3402. ;;
  3403. .mem.offset 0,0
  3404. st8.spill [rpTF1] = t20, TrIntT22-TrIntT20
  3405. .mem.offset 8,0
  3406. st8.spill [rpTF2] = t21, TrIntV0-TrIntT21
  3407. ;;
  3408. .mem.offset 0,0
  3409. st8.spill [rpTF1] = t22, TrBrT0-TrIntT22
  3410. .mem.offset 8,0
  3411. st8.spill [rpTF2] = v0, TrBrT1-TrIntV0 // spill old V0
  3412. ;;
  3413. st8 [rpTF1] = rL2, TrApCCV-TrBrT0 // save old bt0 - bt1
  3414. st8 [rpTF2] = rL3
  3415. mov rL5 = ar.unat
  3416. ;;
  3417. st8 [rpTF1] = rL4, TrSegCSD-TrApCCV // save ar.ccv
  3418. movl rL3 = KiPcr+PcCurrentIrql
  3419. ;;
  3420. st8 [rpTF1] = rL1 // save ar.csd
  3421. add rpTF1 = TrFltT0, sp // point to FltT0
  3422. add rpTF2 = TrFltT1, sp // point to FltT1
  3423. ;;
  3424. //
  3425. // Spill temporary (volatile) floating point registers
  3426. //
  3427. stf.spill [rpTF1] = ft0, TrFltT2-TrFltT0 // spill float tmp 0 - 9
  3428. stf.spill [rpTF2] = ft1, TrFltT3-TrFltT1
  3429. ;;
  3430. stf.spill [rpTF1] = ft2, TrFltT4-TrFltT2
  3431. stf.spill [rpTF2] = ft3, TrFltT5-TrFltT3
  3432. ;;
  3433. stf.spill [rpTF1] = ft4, TrFltT6-TrFltT4
  3434. stf.spill [rpTF2] = ft5, TrFltT7-TrFltT5
  3435. ;;
  3436. stf.spill [rpTF1] = ft6, TrFltT8-TrFltT6
  3437. stf.spill [rpTF2] = ft7, TrFltT9-TrFltT7
  3438. add t20 = TrIntNats, sp
  3439. ;;
  3440. stf.spill [rpTF1] = ft8
  3441. stf.spill [rpTF2] = ft9
  3442. extr.u t5 = t5, TPR_MIC, TPR_MIC_LEN
  3443. ;;
  3444. st8 [t20] = rL5 // save volatile iNats
  3445. st1 [rL3] = t5 // Sanitize currnet IRQL in PCR.
  3446. LEAF_RETURN
  3447. ;;
  3448. LEAF_EXIT(KiSaveTrapFrame)
  3449. //++
  3450. //--------------------------------------------------------------------
  3451. // Routine:
  3452. //
  3453. // VOID
  3454. // KiRestoreTrapFrame(PKTRAP_FRAME)
  3455. //
  3456. // Description:
  3457. //
  3458. // Restore volatile application state from trap frame. Restore CSD
  3459. // Note: sp, brp, RSC, UNAT, predicates, BSP, BSP Store, PFS,
  3460. // CSD and FPSR not restored here.
  3461. //
  3462. // Input:
  3463. //
  3464. // sp: points to trap frame
  3465. // RSE frame size is zero
  3466. //
  3467. // Output:
  3468. //
  3469. // None
  3470. //
  3471. // Return value:
  3472. //
  3473. // none
  3474. //
  3475. //--------------------------------------------------------------------
  3476. LEAF_ENTRY(KiRestoreTrapFrame)
  3477. LEAF_SETUP(0,2,0,0)
  3478. rpTF1 = loc0
  3479. rpTF2 = loc1
  3480. mov t21 = psr
  3481. add t12 = TrIntNats, sp
  3482. add rpTF2 = TrApCCV, sp
  3483. ;;
  3484. ld8 t0 = [t12], TrBrT0-TrIntNats
  3485. ld8 t1 = [rpTF2], TrBrT1-TrApCCV
  3486. add rpTF1 = TrFltT0, sp
  3487. ;;
  3488. ld8 t2 = [t12], TrStFPSR-TrBrT0
  3489. ld8 t3 = [rpTF2], TrSegCSD-TrBrT1
  3490. ;;
  3491. ld8 t10 = [t12]
  3492. ld8 t11 = [rpTF2], TrFltT1-TrSegCSD
  3493. ;;
  3494. ldf.fill ft0 = [rpTF1], TrFltT2-TrFltT0
  3495. ldf.fill ft1 = [rpTF2], TrFltT3-TrFltT1
  3496. ;;
  3497. mov ar.unat = t0
  3498. ldf.fill ft2 = [rpTF1], TrFltT4-TrFltT2
  3499. ldf.fill ft3 = [rpTF2], TrFltT5-TrFltT3
  3500. ;;
  3501. ldf.fill ft4 = [rpTF1], TrFltT6-TrFltT4
  3502. ldf.fill ft5 = [rpTF2], TrFltT7-TrFltT5
  3503. ;;
  3504. ldf.fill ft6 = [rpTF1], TrFltT8-TrFltT6
  3505. ldf.fill ft7 = [rpTF2], TrFltT9-TrFltT7
  3506. ;;
  3507. ldf.fill ft8 = [rpTF1], TrIntGp-TrFltT8
  3508. ldf.fill ft9 = [rpTF2], TrIntT0-TrFltT9
  3509. ;;
  3510. mov ar.ccv = t1
  3511. ld8.fill gp = [rpTF1], TrIntT1-TrIntGp
  3512. ;;
  3513. ld8.fill t0 = [rpTF2], TrIntT2-TrIntT0
  3514. ld8.fill t1 = [rpTF1], TrIntT3-TrIntT1
  3515. mov bt0 = t2
  3516. ;;
  3517. mov ar.csd = t11
  3518. ld8.fill t2 = [rpTF2], TrIntT4-TrIntT2
  3519. mov bt1 = t3
  3520. ;;
  3521. ld8.fill t3 = [rpTF1], TrIntT5-TrIntT3
  3522. tbit.z pt1 = t21, PSR_MFL
  3523. mov ar.fpsr = t10
  3524. ld8.fill t4 = [rpTF2], TrIntT6-TrIntT4
  3525. ;;
  3526. ld8.fill t5 = [rpTF1], TrIntT7-TrIntT5
  3527. ld8.fill t6 = [rpTF2], TrIntT8-TrIntT6
  3528. ;;
  3529. ld8.fill t7 = [rpTF1], TrIntT9-TrIntT7
  3530. ld8.fill t8 = [rpTF2], TrIntT10-TrIntT8
  3531. ;;
  3532. ld8.fill t9 = [rpTF1], TrIntT11-TrIntT9
  3533. ld8.fill t10 = [rpTF2], TrIntT12-TrIntT10
  3534. ;;
  3535. ld8.fill t11 = [rpTF1], TrIntT13-TrIntT11
  3536. ld8.fill t12 = [rpTF2], TrIntT14-TrIntT12
  3537. ;;
  3538. ld8.fill t13 = [rpTF1], TrIntT15-TrIntT13
  3539. ld8.fill t14 = [rpTF2], TrIntT16-TrIntT14
  3540. ;;
  3541. ld8.fill t15 = [rpTF1], TrIntT17-TrIntT15
  3542. ld8.fill t16 = [rpTF2], TrIntT18-TrIntT16
  3543. ;;
  3544. ld8.fill t17 = [rpTF1], TrIntT19-TrIntT17
  3545. ld8.fill t18 = [rpTF2], TrIntT20-TrIntT18
  3546. ;;
  3547. ld8.fill t19 = [rpTF1], TrIntT21-TrIntT19
  3548. ld8.fill t20 = [rpTF2], TrIntT22-TrIntT20
  3549. ;;
  3550. ld8.fill t21 = [rpTF1], TrIntTeb-TrIntT21
  3551. ld8.fill t22 = [rpTF2], TrIntV0-TrIntT22
  3552. ;;
  3553. ld8.fill teb = [rpTF1]
  3554. ld8.fill v0 = [rpTF2]
  3555. br.ret.sptk.many brp
  3556. ;;
  3557. LEAF_EXIT(KiRestoreTrapFrame)
  3558. //++
  3559. //--------------------------------------------------------------------
  3560. // Routine:
  3561. //
  3562. // VOID
  3563. // KiLoadKernelDebugRegisters
  3564. //
  3565. // Description:
  3566. //
  3567. // We maintain two debug register flags:
  3568. // 1. Thread DebugActive: Debug registers active for current thread
  3569. // 2. PCR KernelDebugActive: Debug registers active in kernel mode
  3570. // (setup by kernel debugger)
  3571. //
  3572. // On user -> kernel transitions there are four possibilities:
  3573. //
  3574. // Thread Kernel
  3575. // DebugActive DebugActive Action
  3576. //
  3577. // 1. 0 0 None
  3578. //
  3579. // 2. 1 0 None (kernel PSR.db = 0 by default)
  3580. //
  3581. // 3. 0 1 Set PSR.db = 1 for kernel
  3582. //
  3583. // 4. 1 1 Set PSR.db = 1 for kernel and
  3584. // load kernel debug registers
  3585. //
  3586. // Note we never save the user debug registers:
  3587. // the user cannot change the DRs so the values in the DR save area are
  3588. // always up-to-date (set by SetContext).
  3589. //
  3590. // Input:
  3591. //
  3592. // None (Previous mode is USER)
  3593. //
  3594. // Output:
  3595. //
  3596. // None
  3597. //
  3598. // Return value:
  3599. //
  3600. // none
  3601. //
  3602. //--------------------------------------------------------------------
  3603. NESTED_ENTRY(KiLoadKernelDebugRegisters)
  3604. PROLOGUE_BEGIN
  3605. movl t10 = KiPcr+PcPrcb
  3606. ;;
  3607. ld8 t10 = [t10] // load prcb address
  3608. cmp.eq pt3, pt2 = r0, r0
  3609. ;;
  3610. add t11 = PbProcessorState+KpsSpecialRegisters+KsKernelDbI0,t10
  3611. add t12 = PbProcessorState+KpsSpecialRegisters+KsKernelDbI1,t10
  3612. add t13 = PbProcessorState+KpsSpecialRegisters+KsKernelDbD0,t10
  3613. add t14 = PbProcessorState+KpsSpecialRegisters+KsKernelDbD1,t10
  3614. br Krdr_Common
  3615. ;;
  3616. ALTERNATE_ENTRY(KiLoadUserDebugRegisters)
  3617. //
  3618. // Restore debug registers, if debug active
  3619. //
  3620. cmp.ne pt3, pt2 = r0, r0
  3621. movl t10 = KiPcr+PcCurrentThread
  3622. ;;
  3623. ld8 t10 = [t10] // get current thread pointer
  3624. ;;
  3625. add t10 = ThStackBase, t10
  3626. ;;
  3627. ld8.nta t10 = [t10] // get stack base
  3628. ;;
  3629. add t11 = -ThreadStateSaveAreaLength+TsDebugRegisters+DrDbI0,t10
  3630. add t12 = -ThreadStateSaveAreaLength+TsDebugRegisters+DrDbI1,t10
  3631. add t13 = -ThreadStateSaveAreaLength+TsDebugRegisters+DrDbD0,t10
  3632. add t14 = -ThreadStateSaveAreaLength+TsDebugRegisters+DrDbD1,t10
  3633. ;;
  3634. Krdr_Common:
  3635. .regstk 0, 2, 2, 0
  3636. .save ar.pfs, savedpfs
  3637. alloc savedpfs = ar.pfs, 0, 2, 2, 0
  3638. .save b0, savedbrp
  3639. mov savedbrp = brp
  3640. .save ar.lc, t22
  3641. mov t22 = ar.lc // save ar.lc
  3642. mov t7 = 0
  3643. mov t8 = 1
  3644. PROLOGUE_END
  3645. mov ar.lc = 1 // 2 pairs of debug registers
  3646. ;;
  3647. Krdr_Loop:
  3648. ld8 t1 = [t11], 16 // get dbr pair
  3649. ld8 t2 = [t12], 16 // step by 16 = 1 pair of DRs
  3650. ld8 t3 = [t13], 16 // get dbr pair
  3651. ld8 t4 = [t14], 16 // step by 16 = 1 pair of DRs
  3652. ;;
  3653. .auto
  3654. mov ibr[t7] = t1 // restore ibr pair
  3655. mov ibr[t8] = t2
  3656. .auto
  3657. mov dbr[t7] = t3 // restore dbr pair
  3658. mov dbr[t8] = t4
  3659. ;;
  3660. #ifndef NO_12241
  3661. srlz.d
  3662. #endif
  3663. .default
  3664. add t7 = 2, t7 // next pair
  3665. add t8 = 2, t8
  3666. br.cloop.sptk Krdr_Loop
  3667. ;;
  3668. mov ar.lc = t22 // restore ar.lc
  3669. (pt2) br.ret.sptk brp // return if loading user
  3670. mov out0 = PSR_DB
  3671. mov out1 = 1
  3672. (pt3) br.call.spnt brp = KeSetLowPsrBit // set psr.db if loading kernel
  3673. ;;
  3674. NESTED_RETURN
  3675. ;;
  3676. NESTED_EXIT(KiLoadKernelDebugRegisters)
  3677. //++
  3678. //--------------------------------------------------------------------
  3679. // Routine:
  3680. //
  3681. // VOID
  3682. // KiSaveExceptionFrame(PKEXCEPTION_FRAME)
  3683. //
  3684. // Description:
  3685. //
  3686. // Save preserved context in exception frame.
  3687. //
  3688. // Note: This routine modifies the UNAT register. The caller
  3689. // is resposible for preserving UNAT before calling.
  3690. //
  3691. // Input:
  3692. //
  3693. // a0: points to exception frame
  3694. //
  3695. // Output:
  3696. //
  3697. // None
  3698. //
  3699. // Return value:
  3700. //
  3701. // none
  3702. //
  3703. // Note: t0 may contain the trap frame address; don't touch it.
  3704. //
  3705. //--------------------------------------------------------------------
  3706. LEAF_ENTRY(KiSaveExceptionFrame)
  3707. //
  3708. // Local register aliases
  3709. //
  3710. rpEF1 = t10
  3711. rpEF2 = t11
  3712. add rpEF1 = ExIntS0, a0 // -> ExIntS0
  3713. movl t12 = PFS_EC_MASK << PFS_EC_SHIFT
  3714. ;;
  3715. add rpEF2 = ExIntS1, a0 // -> ExIntS1
  3716. mov t3 = ar.pfs
  3717. ;;
  3718. and t3 = t3, t12
  3719. .mem.offset 0,0
  3720. st8.spill [rpEF1] = s0, ExIntS2-ExIntS0
  3721. .mem.offset 8,0
  3722. st8.spill [rpEF2] = s1, ExIntS3-ExIntS1
  3723. mov t4 = ar.lc
  3724. ;;
  3725. .mem.offset 0,0
  3726. st8.spill [rpEF1] = s2, ExApEC-ExIntS2
  3727. .mem.offset 8,0
  3728. st8.spill [rpEF2] = s3, ExApLC-ExIntS3
  3729. mov t5 = bs0
  3730. ;;
  3731. st8 [rpEF1] = t3, ExBrS0-ExApEC
  3732. st8 [rpEF2] = t4, ExBrS1-ExApLC
  3733. mov t6 = bs1
  3734. ;;
  3735. mov t2 = ar.unat // save user nat register for
  3736. mov t7 = bs2
  3737. mov t8 = bs3
  3738. st8 [rpEF1] = t5, ExBrS2-ExBrS0
  3739. st8 [rpEF2] = t6, ExBrS3-ExBrS1
  3740. mov t9 = bs4
  3741. ;;
  3742. st8 [rpEF1] = t7, ExBrS4-ExBrS2
  3743. st8 [rpEF2] = t8, ExIntNats-ExBrS3
  3744. ;;
  3745. st8 [rpEF1] = t9, ExFltS0-ExBrS4
  3746. st8 [rpEF2] = t2, ExFltS1-ExIntNats
  3747. ;;
  3748. stf.spill [rpEF1] = fs0, ExFltS2-ExFltS0
  3749. stf.spill [rpEF2] = fs1, ExFltS3-ExFltS1
  3750. ;;
  3751. stf.spill [rpEF1] = fs2, ExFltS4-ExFltS2
  3752. stf.spill [rpEF2] = fs3, ExFltS5-ExFltS3
  3753. ;;
  3754. stf.spill [rpEF1] = fs4, ExFltS6-ExFltS4
  3755. stf.spill [rpEF2] = fs5, ExFltS7-ExFltS5
  3756. ;;
  3757. stf.spill [rpEF1] = fs6, ExFltS8-ExFltS6
  3758. stf.spill [rpEF2] = fs7, ExFltS9-ExFltS7
  3759. ;;
  3760. stf.spill [rpEF1] = fs8, ExFltS10-ExFltS8
  3761. stf.spill [rpEF2] = fs9, ExFltS11-ExFltS9
  3762. ;;
  3763. stf.spill [rpEF1] = fs10, ExFltS12-ExFltS10
  3764. stf.spill [rpEF2] = fs11, ExFltS13-ExFltS11
  3765. ;;
  3766. stf.spill [rpEF1] = fs12, ExFltS14-ExFltS12
  3767. stf.spill [rpEF2] = fs13, ExFltS15-ExFltS13
  3768. ;;
  3769. stf.spill [rpEF1] = fs14, ExFltS16-ExFltS14
  3770. stf.spill [rpEF2] = fs15, ExFltS17-ExFltS15
  3771. ;;
  3772. stf.spill [rpEF1] = fs16, ExFltS18-ExFltS16
  3773. stf.spill [rpEF2] = fs17, ExFltS19-ExFltS17
  3774. ;;
  3775. stf.spill [rpEF1] = fs18
  3776. stf.spill [rpEF2] = fs19
  3777. LEAF_RETURN
  3778. ;;
  3779. LEAF_EXIT(KiSaveExceptionFrame)
  3780. //--------------------------------------------------------------------
  3781. // Routine:
  3782. //
  3783. // VOID
  3784. // KiRestoreExceptionFrame(PKEXCEPTION_FRAME)
  3785. //
  3786. // Description:
  3787. //
  3788. // Restores preserved context from the exception frame. Also
  3789. // restore volatile part of floating point context not restored with
  3790. // rest of volatile context.
  3791. //
  3792. // Note: This routine does not use v0, t21 or t22. This routine's
  3793. // caller may be dependent on these registers (for performance
  3794. // in the context switch path).
  3795. //
  3796. // Note: This routine modifies the UNAT register. The caller
  3797. // is resposible for restoring UNAT to the correct value.
  3798. //
  3799. // Input:
  3800. //
  3801. // a0: points to exception frame
  3802. //
  3803. // Output:
  3804. //
  3805. // None
  3806. //
  3807. // Return value:
  3808. //
  3809. // none
  3810. //
  3811. //--------------------------------------------------------------------
  3812. LEAF_ENTRY(KiRestoreExceptionFrame)
  3813. add t16 = ExIntNats, a0
  3814. movl t12 = PFS_EC_MASK << PFS_EC_SHIFT
  3815. add t17 = ExApEC, a0
  3816. nop.f 0
  3817. mov t13 = ar.pfs
  3818. ;;
  3819. ld8.nta t2 = [t16], ExBrS0-ExIntNats
  3820. ld8.nta t3 = [t17], ExApLC-ExApEC
  3821. ;;
  3822. ld8.nta t5 = [t16], ExBrS1-ExBrS0
  3823. ld8.nta t4 = [t17], ExBrS2-ExApLC
  3824. ;;
  3825. ld8.nta t6 = [t16], ExBrS3-ExBrS1
  3826. ld8.nta t7 = [t17], ExBrS4-ExBrS2
  3827. ;;
  3828. ld8.nta t8 = [t16], ExFltS0-ExBrS3
  3829. ld8.nta t9 = [t17], ExFltS1-ExBrS4
  3830. ;;
  3831. ldf.fill.nta fs0 = [t16], ExFltS2-ExFltS0
  3832. ldf.fill.nta fs1 = [t17], ExFltS3-ExFltS1
  3833. add t18 = ExIntS0, a0
  3834. ;;
  3835. ldf.fill.nta fs2 = [t16], ExFltS4-ExFltS2
  3836. ldf.fill.nta fs3 = [t17], ExFltS5-ExFltS3
  3837. add t19 = ExIntS1, a0
  3838. ;;
  3839. ldf.fill.nta fs4 = [t16], ExFltS6-ExFltS4
  3840. ldf.fill.nta fs5 = [t17], ExFltS7-ExFltS5
  3841. andcm t13 = t13, t12 // zero out EC field
  3842. ;;
  3843. ldf.fill.nta fs6 = [t16], ExFltS8-ExFltS6
  3844. ldf.fill.nta fs7 = [t17], ExFltS9-ExFltS7
  3845. and t3 = t3, t12 // capture EC value
  3846. ;;
  3847. mov ar.unat = t2
  3848. or t13 = t3, t13 // deposit into PFS.EC field
  3849. ;;
  3850. ldf.fill.nta fs8 = [t16], ExFltS10-ExFltS8
  3851. ldf.fill.nta fs9 = [t17], ExFltS11-ExFltS9
  3852. mov ar.pfs = t13
  3853. ;;
  3854. ldf.fill.nta fs10 = [t16], ExFltS12-ExFltS10
  3855. ldf.fill.nta fs11 = [t17], ExFltS13-ExFltS11
  3856. mov ar.lc = t4
  3857. ;;
  3858. ldf.fill.nta fs12 = [t16], ExFltS14-ExFltS12
  3859. ldf.fill.nta fs13 = [t17], ExFltS15-ExFltS13
  3860. mov bs0 = t5
  3861. ;;
  3862. ldf.fill.nta fs14 = [t16], ExFltS16-ExFltS14
  3863. ldf.fill.nta fs15 = [t17], ExFltS17-ExFltS15
  3864. mov bs1 = t6
  3865. ;;
  3866. ldf.fill.nta fs16 = [t16], ExFltS18-ExFltS16
  3867. ldf.fill.nta fs17 = [t17], ExFltS19-ExFltS17
  3868. mov bs2 = t7
  3869. ;;
  3870. ldf.fill.nta fs18 = [t16]
  3871. ldf.fill.nta fs19 = [t17]
  3872. mov bs3 = t8
  3873. ld8.fill.nta s0 = [t18], ExIntS2-ExIntS0
  3874. ld8.fill.nta s1 = [t19], ExIntS3-ExIntS1
  3875. mov bs4 = t9
  3876. ;;
  3877. ld8.fill.nta s2 = [t18]
  3878. ld8.fill.nta s3 = [t19]
  3879. LEAF_RETURN
  3880. ;;
  3881. LEAF_EXIT(KiRestoreExceptionFrame)
  3882. //++
  3883. //--------------------------------------------------------------------
  3884. // Routine:
  3885. //
  3886. // KiSaveHigherFPVolatile(PKHIGHER_FP_SAVEAREA)
  3887. //
  3888. // Description:
  3889. //
  3890. // Save higher FP volatile context in higher FP save area
  3891. //
  3892. // Input:
  3893. //
  3894. // a0: pointer to higher FP save area
  3895. // brp: return address
  3896. //
  3897. // Output:
  3898. //
  3899. // None
  3900. //
  3901. // Return value:
  3902. //
  3903. // None
  3904. //
  3905. //--------------------------------------------------------------------
  3906. NESTED_ENTRY(KiSaveHigherFPVolatile)
  3907. NESTED_SETUP(1, 3, 1, 0)
  3908. PROLOGUE_END
  3909. //
  3910. // Local register aliases
  3911. //
  3912. rpSA1 = t0
  3913. rpSA2 = t1
  3914. //
  3915. // Clear DFH bit so the high floating point set may be saved by the kernel
  3916. // Disable interrupts so that save is atomic
  3917. //
  3918. GET_IRQL (loc2)
  3919. mov t2 = psr.um
  3920. movl t3 = KiPcr+PcCurrentThread
  3921. ;;
  3922. cmp.ge pt2, pt3 = APC_LEVEL, loc2
  3923. ;;
  3924. PSET_IRQL (pt2, DISPATCH_LEVEL)
  3925. ld8 t4 = [t3], PcHighFpOwner-PcCurrentThread
  3926. ;;
  3927. ld8 t5 = [t3]
  3928. ;;
  3929. cmp.ne pt1 = t4, t5
  3930. (pt1) br.cond.spnt Kshfpv20
  3931. ;;
  3932. tbit.z pt0 = t2, PSR_MFH
  3933. (pt0) br.cond.spnt Kshfpv20
  3934. br Kshfpv10
  3935. ;;
  3936. ALTERNATE_ENTRY(KiSaveHigherFPVolatileAtDispatchLevel)
  3937. NESTED_SETUP(1, 3, 1, 0)
  3938. cmp.ne pt2, pt3 = r0, r0 // set pt2 to FALSE, pt3 to TRUE
  3939. PROLOGUE_END
  3940. movl t3 = KiPcr+PcCurrentThread
  3941. ;;
  3942. ld8 t4 = [t3], PcHighFpOwner-PcCurrentThread
  3943. ;;
  3944. ld8 t5 = [t3]
  3945. ;;
  3946. cmp.ne pt1 = t4, t5
  3947. ;;
  3948. (pt1) break.i BREAKPOINT_STOP
  3949. Kshfpv10:
  3950. rsm (1 << PSR_DFH)
  3951. add rpSA1 = HiFltF32, a0 // -> HiFltF32
  3952. add rpSA2 = HiFltF33, a0 // -> HiFltF33
  3953. ;;
  3954. srlz.d
  3955. stf.spill.nta [rpSA1] = f32, HiFltF34-HiFltF32
  3956. stf.spill.nta [rpSA2] = f33, HiFltF35-HiFltF33
  3957. ;;
  3958. stf.spill.nta [rpSA1] = f34, HiFltF36-HiFltF34
  3959. stf.spill.nta [rpSA2] = f35, HiFltF37-HiFltF35
  3960. ;;
  3961. stf.spill.nta [rpSA1] = f36, HiFltF38-HiFltF36
  3962. stf.spill.nta [rpSA2] = f37, HiFltF39-HiFltF37
  3963. ;;
  3964. stf.spill.nta [rpSA1] = f38, HiFltF40-HiFltF38
  3965. stf.spill.nta [rpSA2] = f39, HiFltF41-HiFltF39
  3966. ;;
  3967. stf.spill.nta [rpSA1] = f40, HiFltF42-HiFltF40
  3968. stf.spill.nta [rpSA2] = f41, HiFltF43-HiFltF41
  3969. ;;
  3970. stf.spill.nta [rpSA1] = f42, HiFltF44-HiFltF42
  3971. stf.spill.nta [rpSA2] = f43, HiFltF45-HiFltF43
  3972. ;;
  3973. stf.spill.nta [rpSA1] = f44, HiFltF46-HiFltF44
  3974. stf.spill.nta [rpSA2] = f45, HiFltF47-HiFltF45
  3975. ;;
  3976. stf.spill.nta [rpSA1] = f46, HiFltF48-HiFltF46
  3977. stf.spill.nta [rpSA2] = f47, HiFltF49-HiFltF47
  3978. ;;
  3979. stf.spill.nta [rpSA1] = f48, HiFltF50-HiFltF48
  3980. stf.spill.nta [rpSA2] = f49, HiFltF51-HiFltF49
  3981. ;;
  3982. stf.spill.nta [rpSA1] = f50, HiFltF52-HiFltF50
  3983. stf.spill.nta [rpSA2] = f51, HiFltF53-HiFltF51
  3984. ;;
  3985. stf.spill.nta [rpSA1] = f52, HiFltF54-HiFltF52
  3986. stf.spill.nta [rpSA2] = f53, HiFltF55-HiFltF53
  3987. ;;
  3988. stf.spill.nta [rpSA1] = f54, HiFltF56-HiFltF54
  3989. stf.spill.nta [rpSA2] = f55, HiFltF57-HiFltF55
  3990. ;;
  3991. stf.spill.nta [rpSA1] = f56, HiFltF58-HiFltF56
  3992. stf.spill.nta [rpSA2] = f57, HiFltF59-HiFltF57
  3993. ;;
  3994. stf.spill.nta [rpSA1] = f58, HiFltF60-HiFltF58
  3995. stf.spill.nta [rpSA2] = f59, HiFltF61-HiFltF59
  3996. ;;
  3997. stf.spill.nta [rpSA1] = f60, HiFltF62-HiFltF60
  3998. stf.spill.nta [rpSA2] = f61, HiFltF63-HiFltF61
  3999. ;;
  4000. stf.spill.nta [rpSA1] = f62, HiFltF64-HiFltF62
  4001. stf.spill.nta [rpSA2] = f63, HiFltF65-HiFltF63
  4002. ;;
  4003. stf.spill.nta [rpSA1] = f64, HiFltF66-HiFltF64
  4004. stf.spill.nta [rpSA2] = f65, HiFltF67-HiFltF65
  4005. ;;
  4006. stf.spill.nta [rpSA1] = f66, HiFltF68-HiFltF66
  4007. stf.spill.nta [rpSA2] = f67, HiFltF69-HiFltF67
  4008. ;;
  4009. stf.spill.nta [rpSA1] = f68, HiFltF70-HiFltF68
  4010. stf.spill.nta [rpSA2] = f69, HiFltF71-HiFltF69
  4011. ;;
  4012. stf.spill.nta [rpSA1] = f70, HiFltF72-HiFltF70
  4013. stf.spill.nta [rpSA2] = f71, HiFltF73-HiFltF71
  4014. ;;
  4015. stf.spill.nta [rpSA1] = f72, HiFltF74-HiFltF72
  4016. stf.spill.nta [rpSA2] = f73, HiFltF75-HiFltF73
  4017. ;;
  4018. stf.spill.nta [rpSA1] = f74, HiFltF76-HiFltF74
  4019. stf.spill.nta [rpSA2] = f75, HiFltF77-HiFltF75
  4020. ;;
  4021. stf.spill.nta [rpSA1] = f76, HiFltF78-HiFltF76
  4022. stf.spill.nta [rpSA2] = f77, HiFltF79-HiFltF77
  4023. ;;
  4024. stf.spill.nta [rpSA1] = f78, HiFltF80-HiFltF78
  4025. stf.spill.nta [rpSA2] = f79, HiFltF81-HiFltF79
  4026. ;;
  4027. stf.spill.nta [rpSA1] = f80, HiFltF82-HiFltF80
  4028. stf.spill.nta [rpSA2] = f81, HiFltF83-HiFltF81
  4029. ;;
  4030. stf.spill.nta [rpSA1] = f82, HiFltF84-HiFltF82
  4031. stf.spill.nta [rpSA2] = f83, HiFltF85-HiFltF83
  4032. ;;
  4033. stf.spill.nta [rpSA1] = f84, HiFltF86-HiFltF84
  4034. stf.spill.nta [rpSA2] = f85, HiFltF87-HiFltF85
  4035. ;;
  4036. stf.spill.nta [rpSA1] = f86, HiFltF88-HiFltF86
  4037. stf.spill.nta [rpSA2] = f87, HiFltF89-HiFltF87
  4038. ;;
  4039. stf.spill.nta [rpSA1] = f88, HiFltF90-HiFltF88
  4040. stf.spill.nta [rpSA2] = f89, HiFltF91-HiFltF89
  4041. ;;
  4042. stf.spill.nta [rpSA1] = f90, HiFltF92-HiFltF90
  4043. stf.spill.nta [rpSA2] = f91, HiFltF93-HiFltF91
  4044. ;;
  4045. stf.spill.nta [rpSA1] = f92, HiFltF94-HiFltF92
  4046. stf.spill.nta [rpSA2] = f93, HiFltF95-HiFltF93
  4047. ;;
  4048. stf.spill.nta [rpSA1] = f94, HiFltF96-HiFltF94
  4049. stf.spill.nta [rpSA2] = f95, HiFltF97-HiFltF95
  4050. ;;
  4051. stf.spill.nta [rpSA1] = f96, HiFltF98-HiFltF96
  4052. stf.spill.nta [rpSA2] = f97, HiFltF99-HiFltF97
  4053. ;;
  4054. stf.spill.nta [rpSA1] = f98, HiFltF100-HiFltF98
  4055. stf.spill.nta [rpSA2] = f99, HiFltF101-HiFltF99
  4056. ;;
  4057. stf.spill.nta [rpSA1] = f100, HiFltF102-HiFltF100
  4058. stf.spill.nta [rpSA2] = f101, HiFltF103-HiFltF101
  4059. ;;
  4060. stf.spill.nta [rpSA1] = f102, HiFltF104-HiFltF102
  4061. stf.spill.nta [rpSA2] = f103, HiFltF105-HiFltF103
  4062. ;;
  4063. stf.spill.nta [rpSA1] = f104, HiFltF106-HiFltF104
  4064. stf.spill.nta [rpSA2] = f105, HiFltF107-HiFltF105
  4065. ;;
  4066. stf.spill.nta [rpSA1] = f106, HiFltF108-HiFltF106
  4067. stf.spill.nta [rpSA2] = f107, HiFltF109-HiFltF107
  4068. ;;
  4069. stf.spill.nta [rpSA1] = f108, HiFltF110-HiFltF108
  4070. stf.spill.nta [rpSA2] = f109, HiFltF111-HiFltF109
  4071. ;;
  4072. stf.spill.nta [rpSA1] = f110, HiFltF112-HiFltF110
  4073. stf.spill.nta [rpSA2] = f111, HiFltF113-HiFltF111
  4074. ;;
  4075. stf.spill.nta [rpSA1] = f112, HiFltF114-HiFltF112
  4076. stf.spill.nta [rpSA2] = f113, HiFltF115-HiFltF113
  4077. ;;
  4078. stf.spill.nta [rpSA1] = f114, HiFltF116-HiFltF114
  4079. stf.spill.nta [rpSA2] = f115, HiFltF117-HiFltF115
  4080. ;;
  4081. stf.spill.nta [rpSA1] = f116, HiFltF118-HiFltF116
  4082. stf.spill.nta [rpSA2] = f117, HiFltF119-HiFltF117
  4083. ;;
  4084. stf.spill.nta [rpSA1] = f118, HiFltF120-HiFltF118
  4085. stf.spill.nta [rpSA2] = f119, HiFltF121-HiFltF119
  4086. ;;
  4087. stf.spill.nta [rpSA1] = f120, HiFltF122-HiFltF120
  4088. stf.spill.nta [rpSA2] = f121, HiFltF123-HiFltF121
  4089. ;;
  4090. stf.spill.nta [rpSA1] = f122, HiFltF124-HiFltF122
  4091. stf.spill.nta [rpSA2] = f123, HiFltF125-HiFltF123
  4092. ;;
  4093. stf.spill.nta [rpSA1] = f124, HiFltF126-HiFltF124
  4094. stf.spill.nta [rpSA2] = f125, HiFltF127-HiFltF125
  4095. ;;
  4096. stf.spill.nta [rpSA1] = f126
  4097. stf.spill.nta [rpSA2] = f127
  4098. //
  4099. // Set DFH bit so the high floating point set may not be used by the kernel
  4100. // Must clear mfh after fp registers saved
  4101. //
  4102. Kshfpv20:
  4103. ssm 1 << PSR_DFH
  4104. ;;
  4105. rum 1 << PSR_MFH
  4106. (pt3) br.ret.sptk brp
  4107. LOWER_IRQL(loc2)
  4108. NESTED_RETURN
  4109. ;;
  4110. LEAF_EXIT(KiSaveHigherFPVolatile)
  4111. //++
  4112. //--------------------------------------------------------------------
  4113. // Routine:
  4114. //
  4115. // KiRestoreHigherFPVolatile()
  4116. //
  4117. // Description:
  4118. //
  4119. // Restore higher FP volatile context from higher FP save area
  4120. //
  4121. // N.B. This function is carefully constructed to use only scratch
  4122. // registers rHpT1, rHpT3, and rTH2. This function may be
  4123. // called by C code and the disabled fp vector when user
  4124. // and kernel bank is used respectively.
  4125. // N.B. Caller must ensure higher fp enabled (psr.dfh=0)
  4126. // N.B. Caller must ensure no interrupt during restore
  4127. //
  4128. // Input:
  4129. //
  4130. // None.
  4131. //
  4132. // Output:
  4133. //
  4134. // None
  4135. //
  4136. // Return value:
  4137. //
  4138. // None
  4139. //
  4140. //--------------------------------------------------------------------
  4141. LEAF_ENTRY(KiRestoreHigherFPVolatile)
  4142. movl rHpT1 = KiPcr+PcCurrentThread
  4143. ;;
  4144. ld8 rHpT3 = [rHpT1], PcHighFpOwner-PcCurrentThread
  4145. ;;
  4146. st8 [rHpT1] = rHpT3, PcNumber-PcHighFpOwner
  4147. add rHpT3 = ThNumber, rHpT3
  4148. ;;
  4149. ld1 rHpT1 = [rHpT1] // load processor #
  4150. ;;
  4151. st1 [rHpT3] = rHpT1 // save it in Thread->Number
  4152. add rHpT3 = ThStackBase-ThNumber, rHpT3
  4153. ;;
  4154. ld8 rHpT3 = [rHpT3] // load kernel stack base
  4155. ;;
  4156. add rHpT1 = -ThreadStateSaveAreaLength+TsHigherFPVolatile+HiFltF32, rHpT3
  4157. add rHpT3 = -ThreadStateSaveAreaLength+TsHigherFPVolatile+HiFltF33, rHpT3
  4158. ;;
  4159. ldf.fill.nta f32 = [rHpT1], HiFltF34-HiFltF32
  4160. ldf.fill.nta f33 = [rHpT3], HiFltF35-HiFltF33
  4161. ;;
  4162. ldf.fill.nta f34 = [rHpT1], HiFltF36-HiFltF34
  4163. ldf.fill.nta f35 = [rHpT3], HiFltF37-HiFltF35
  4164. ;;
  4165. ldf.fill.nta f36 = [rHpT1], HiFltF38-HiFltF36
  4166. ldf.fill.nta f37 = [rHpT3], HiFltF39-HiFltF37
  4167. ;;
  4168. ldf.fill.nta f38 = [rHpT1], HiFltF40-HiFltF38
  4169. ldf.fill.nta f39 = [rHpT3], HiFltF41-HiFltF39
  4170. ;;
  4171. ldf.fill.nta f40 = [rHpT1], HiFltF42-HiFltF40
  4172. ldf.fill.nta f41 = [rHpT3], HiFltF43-HiFltF41
  4173. ;;
  4174. ldf.fill.nta f42 = [rHpT1], HiFltF44-HiFltF42
  4175. ldf.fill.nta f43 = [rHpT3], HiFltF45-HiFltF43
  4176. ;;
  4177. ldf.fill.nta f44 = [rHpT1], HiFltF46-HiFltF44
  4178. ldf.fill.nta f45 = [rHpT3], HiFltF47-HiFltF45
  4179. ;;
  4180. ldf.fill.nta f46 = [rHpT1], HiFltF48-HiFltF46
  4181. ldf.fill.nta f47 = [rHpT3], HiFltF49-HiFltF47
  4182. ;;
  4183. ldf.fill.nta f48 = [rHpT1], HiFltF50-HiFltF48
  4184. ldf.fill.nta f49 = [rHpT3], HiFltF51-HiFltF49
  4185. ;;
  4186. ldf.fill.nta f50 = [rHpT1], HiFltF52-HiFltF50
  4187. ldf.fill.nta f51 = [rHpT3], HiFltF53-HiFltF51
  4188. ;;
  4189. ldf.fill.nta f52 = [rHpT1], HiFltF54-HiFltF52
  4190. ldf.fill.nta f53 = [rHpT3], HiFltF55-HiFltF53
  4191. ;;
  4192. ldf.fill.nta f54 = [rHpT1], HiFltF56-HiFltF54
  4193. ldf.fill.nta f55 = [rHpT3], HiFltF57-HiFltF55
  4194. ;;
  4195. ldf.fill.nta f56 = [rHpT1], HiFltF58-HiFltF56
  4196. ldf.fill.nta f57 = [rHpT3], HiFltF59-HiFltF57
  4197. ;;
  4198. ldf.fill.nta f58 = [rHpT1], HiFltF60-HiFltF58
  4199. ldf.fill.nta f59 = [rHpT3], HiFltF61-HiFltF59
  4200. ;;
  4201. ldf.fill.nta f60 = [rHpT1], HiFltF62-HiFltF60
  4202. ldf.fill.nta f61 = [rHpT3], HiFltF63-HiFltF61
  4203. ;;
  4204. ldf.fill.nta f62 = [rHpT1], HiFltF64-HiFltF62
  4205. ldf.fill.nta f63 = [rHpT3], HiFltF65-HiFltF63
  4206. ;;
  4207. ldf.fill.nta f64 = [rHpT1], HiFltF66-HiFltF64
  4208. ldf.fill.nta f65 = [rHpT3], HiFltF67-HiFltF65
  4209. ;;
  4210. ldf.fill.nta f66 = [rHpT1], HiFltF68-HiFltF66
  4211. ldf.fill.nta f67 = [rHpT3], HiFltF69-HiFltF67
  4212. ;;
  4213. ldf.fill.nta f68 = [rHpT1], HiFltF70-HiFltF68
  4214. ldf.fill.nta f69 = [rHpT3], HiFltF71-HiFltF69
  4215. ;;
  4216. ldf.fill.nta f70 = [rHpT1], HiFltF72-HiFltF70
  4217. ldf.fill.nta f71 = [rHpT3], HiFltF73-HiFltF71
  4218. ;;
  4219. ldf.fill.nta f72 = [rHpT1], HiFltF74-HiFltF72
  4220. ldf.fill.nta f73 = [rHpT3], HiFltF75-HiFltF73
  4221. ;;
  4222. ldf.fill.nta f74 = [rHpT1], HiFltF76-HiFltF74
  4223. ldf.fill.nta f75 = [rHpT3], HiFltF77-HiFltF75
  4224. ;;
  4225. ldf.fill.nta f76 = [rHpT1], HiFltF78-HiFltF76
  4226. ldf.fill.nta f77 = [rHpT3], HiFltF79-HiFltF77
  4227. ;;
  4228. ldf.fill.nta f78 = [rHpT1], HiFltF80-HiFltF78
  4229. ldf.fill.nta f79 = [rHpT3], HiFltF81-HiFltF79
  4230. ;;
  4231. ldf.fill.nta f80 = [rHpT1], HiFltF82-HiFltF80
  4232. ldf.fill.nta f81 = [rHpT3], HiFltF83-HiFltF81
  4233. ;;
  4234. ldf.fill.nta f82 = [rHpT1], HiFltF84-HiFltF82
  4235. ldf.fill.nta f83 = [rHpT3], HiFltF85-HiFltF83
  4236. ;;
  4237. ldf.fill.nta f84 = [rHpT1], HiFltF86-HiFltF84
  4238. ldf.fill.nta f85 = [rHpT3], HiFltF87-HiFltF85
  4239. ;;
  4240. ldf.fill.nta f86 = [rHpT1], HiFltF88-HiFltF86
  4241. ldf.fill.nta f87 = [rHpT3], HiFltF89-HiFltF87
  4242. ;;
  4243. ldf.fill.nta f88 = [rHpT1], HiFltF90-HiFltF88
  4244. ldf.fill.nta f89 = [rHpT3], HiFltF91-HiFltF89
  4245. ;;
  4246. ldf.fill.nta f90 = [rHpT1], HiFltF92-HiFltF90
  4247. ldf.fill.nta f91 = [rHpT3], HiFltF93-HiFltF91
  4248. ;;
  4249. ldf.fill.nta f92 = [rHpT1], HiFltF94-HiFltF92
  4250. ldf.fill.nta f93 = [rHpT3], HiFltF95-HiFltF93
  4251. ;;
  4252. ldf.fill.nta f94 = [rHpT1], HiFltF96-HiFltF94
  4253. ldf.fill.nta f95 = [rHpT3], HiFltF97-HiFltF95
  4254. ;;
  4255. ldf.fill.nta f96 = [rHpT1], HiFltF98-HiFltF96
  4256. ldf.fill.nta f97 = [rHpT3], HiFltF99-HiFltF97
  4257. ;;
  4258. ldf.fill.nta f98 = [rHpT1], HiFltF100-HiFltF98
  4259. ldf.fill.nta f99 = [rHpT3], HiFltF101-HiFltF99
  4260. ;;
  4261. ldf.fill.nta f100 = [rHpT1], HiFltF102-HiFltF100
  4262. ldf.fill.nta f101 = [rHpT3], HiFltF103-HiFltF101
  4263. ;;
  4264. ldf.fill.nta f102 = [rHpT1], HiFltF104-HiFltF102
  4265. ldf.fill.nta f103 = [rHpT3], HiFltF105-HiFltF103
  4266. ;;
  4267. ldf.fill.nta f104 = [rHpT1], HiFltF106-HiFltF104
  4268. ldf.fill.nta f105 = [rHpT3], HiFltF107-HiFltF105
  4269. ;;
  4270. ldf.fill.nta f106 = [rHpT1], HiFltF108-HiFltF106
  4271. ldf.fill.nta f107 = [rHpT3], HiFltF109-HiFltF107
  4272. ;;
  4273. ldf.fill.nta f108 = [rHpT1], HiFltF110-HiFltF108
  4274. ldf.fill.nta f109 = [rHpT3], HiFltF111-HiFltF109
  4275. ;;
  4276. ldf.fill.nta f110 = [rHpT1], HiFltF112-HiFltF110
  4277. ldf.fill.nta f111 = [rHpT3], HiFltF113-HiFltF111
  4278. ;;
  4279. ldf.fill.nta f112 = [rHpT1], HiFltF114-HiFltF112
  4280. ldf.fill.nta f113 = [rHpT3], HiFltF115-HiFltF113
  4281. ;;
  4282. ldf.fill.nta f114 = [rHpT1], HiFltF116-HiFltF114
  4283. ldf.fill.nta f115 = [rHpT3], HiFltF117-HiFltF115
  4284. ;;
  4285. ldf.fill.nta f116 = [rHpT1], HiFltF118-HiFltF116
  4286. ldf.fill.nta f117 = [rHpT3], HiFltF119-HiFltF117
  4287. ;;
  4288. ldf.fill.nta f118 = [rHpT1], HiFltF120-HiFltF118
  4289. ldf.fill.nta f119 = [rHpT3], HiFltF121-HiFltF119
  4290. ;;
  4291. ldf.fill.nta f120 = [rHpT1], HiFltF122-HiFltF120
  4292. ldf.fill.nta f121 = [rHpT3], HiFltF123-HiFltF121
  4293. ;;
  4294. ldf.fill.nta f122 = [rHpT1], HiFltF124-HiFltF122
  4295. ldf.fill.nta f123 = [rHpT3], HiFltF125-HiFltF123
  4296. ;;
  4297. ldf.fill.nta f124 = [rHpT1], HiFltF126-HiFltF124
  4298. ldf.fill.nta f125 = [rHpT3], HiFltF127-HiFltF125
  4299. ;;
  4300. ldf.fill.nta f126 = [rHpT1]
  4301. ldf.fill.nta f127 = [rHpT3]
  4302. ;;
  4303. rsm 1 << PSR_MFH // clear psr.mfh bit
  4304. br.ret.sptk brp
  4305. ;;
  4306. LEAF_EXIT(KiRestoreHigherFPVolatile)
  4307. //
  4308. // ++
  4309. //
  4310. // Routine:
  4311. //
  4312. // KiPageTableFault
  4313. //
  4314. // Description:
  4315. //
  4316. // Branched from Inst/DataTlbVector
  4317. // Inserts a missing PDE translation for VHPT mapping
  4318. // If PageNotPresent-bit of PDE is not set,
  4319. // branches out to KiPageFault
  4320. //
  4321. // On entry:
  4322. //
  4323. // rva (h24) : offending virtual address
  4324. // riha (h25) : a offending PTE address
  4325. // rpr: (h26) : saved predicate
  4326. //
  4327. // Handle:
  4328. //
  4329. // Extracts the PDE index from riha (PTE address in VHPT) and
  4330. // generates a PDE address by adding to VHPT_DIRBASE. When accesses
  4331. // a page directory entry (PDE), there might be a TLB miss on the
  4332. // page directory table and returns a NaT on ld8.s. If so, branches
  4333. // to KiPageDirectoryTableFault. If the page-not-present bit of the
  4334. // PDE is not set, branches to KiPageNotPresentFault. Otherwise,
  4335. // inserts the PDE entry into the data TC (translation cache).
  4336. //
  4337. // Notes:
  4338. //
  4339. //
  4340. // --
  4341. HANDLER_ENTRY(KiPageTableFault)
  4342. rva = h24
  4343. riha = h25
  4344. rpr = h26
  4345. rpPde = h27
  4346. rPde = h28
  4347. rPde2 = h29
  4348. rps = h30
  4349. rISR = h31
  4350. thash rpPde = riha // M
  4351. cmp.ne pt1 = r0, r0
  4352. mov rps = PAGE_SHIFT << PS_SHIFT // I
  4353. ;;
  4354. mov cr.itir = rps // M
  4355. ld8.s rPde = [rpPde] // M, load PDE
  4356. ;;
  4357. extr.u rPde2 = rPde, 2, 3 // I
  4358. tnat.nz pt0, p0 = rPde // I
  4359. tbit.z.or pt1, p0 = rPde, PTE_ACCESS
  4360. tbit.z.or pt1, p0 = rPde, PTE_VALID // I, if non-present page fault
  4361. (pt0) br.cond.spnt KiPageDirectoryFault // B, tb miss on PDE access
  4362. (pt1) br.cond.spnt KiPageFault // B, page fault
  4363. ;;
  4364. cmp.eq pt3 = 1, rPde2 // A
  4365. mov cr.ifa = riha // M
  4366. (pt3) br.cond.spnt KiLargePage
  4367. ;;
  4368. itc.d rPde // M
  4369. ;;
  4370. #if !defined(NT_UP)
  4371. ld8.s rPde2 = [rpPde] // M
  4372. cmp.ne pt0 = zero, zero // I
  4373. ;;
  4374. cmp.ne.or pt0, p0 = rPde2, rPde // I, if PTEs are different
  4375. tnat.nz.or pt0, p0 = rPde2 // I
  4376. ;;
  4377. (pt0) ptc.l riha, rps // M, purge it
  4378. #endif
  4379. mov pr = rpr, -1 // I
  4380. rfi;; // B
  4381. //
  4382. // This is a large page PDE entry.
  4383. //
  4384. KiLargePage:
  4385. mov cr.ifa = rva // M
  4386. mov rISR = cr.isr
  4387. extr.u rPde2 = rPde, PTE_LP_CACHE_SHIFT, PTE_CACHE_LEN
  4388. ;;
  4389. mov rps = LARGE_PAGE_SHIFT << PS_SHIFT
  4390. dep rPde2 = rPde2, rPde, 2, 3 // Set the cachable attribute.
  4391. ;;
  4392. mov cr.itir = rps // M
  4393. tbit.z pt3, pt4 = rISR, ISR_X // I
  4394. ;;
  4395. (pt3) itc.d rPde2 // M
  4396. ;;
  4397. (pt4) itc.i rPde2 // M
  4398. ;;
  4399. #if !defined(NT_UP)
  4400. ld8.s rPde2 = [rpPde] // M
  4401. cmp.ne pt0 = zero, zero // I
  4402. ;;
  4403. cmp.ne.or pt0, p0 = rPde2, rPde // I, if PTEs are different
  4404. tnat.nz.or pt0, p0 = rPde2 // I
  4405. ;;
  4406. (pt0) ptc.l rva, rps // M, purge it
  4407. #endif
  4408. mov pr = rpr, -1 // I
  4409. rfi;; // B
  4410. HANDLER_EXIT(KiPageTableFault)
  4411. //++
  4412. //
  4413. // KiPageDirectoryFault
  4414. //
  4415. // Cause:
  4416. //
  4417. // Parameters:
  4418. // rpPde (h28) : pointer to PDE entry
  4419. // rpr (h26) : saved predicate
  4420. //
  4421. //
  4422. // Handle:
  4423. //
  4424. //--
  4425. HANDLER_ENTRY(KiPageDirectoryFault)
  4426. rva = h24
  4427. rpPpe = h25
  4428. rpr = h26
  4429. rpPde = h27
  4430. rPpe = h28
  4431. rPpe2 = h29
  4432. rps = h30
  4433. thash rpPpe = rpPde // M
  4434. cmp.ne pt0 = r0, r0
  4435. ;;
  4436. ld8.s rPpe = [rpPpe] // M
  4437. ;;
  4438. tnat.nz.or pt0, p0 = rPpe // I
  4439. tbit.z.or pt0, p0 = rPpe, PTE_ACCESS
  4440. tbit.z.or pt0, p0 = rPpe, PTE_VALID // I, if non-present page fault
  4441. (pt0) br.cond.spnt KiPageFault // B
  4442. ;;
  4443. mov cr.ifa = rpPde // M, set tva for vhpt translation
  4444. ;;
  4445. itc.d rPpe // M
  4446. ;;
  4447. #if !defined(NT_UP)
  4448. ld8.s rPpe2 = [rpPpe] // M
  4449. mov rps = PAGE_SHIFT << PS_SHIFT // I
  4450. cmp.ne pt0 = zero, zero // I
  4451. ;;
  4452. cmp.ne.or pt0, p0 = rPpe2, rPpe // I, if PTEs are different
  4453. tnat.nz.or pt0, p0 = rPpe2 // I
  4454. ;;
  4455. (pt0) ptc.l rpPde, rps // M, purge it
  4456. #endif
  4457. mov pr = rpr, -1 // I
  4458. rfi;; // B
  4459. HANDLER_EXIT(KiPageDirectoryFault)
  4460. //
  4461. // ++
  4462. //
  4463. // Routine:
  4464. //
  4465. // KiPteNotPresentFault
  4466. //
  4467. // Description:
  4468. //
  4469. // Branched from KiVhptTransVector and KiPageTableFault.
  4470. // Inserts a missing PDE translation for VHPT mapping
  4471. // If no PDE for it, branches out to KiPageFault
  4472. //
  4473. // On entry:
  4474. //
  4475. // rva (h24) : offending virtual address
  4476. // rpr (h26) : saved predicate
  4477. // rPde (h28) : PDE entry
  4478. //
  4479. // Handle:
  4480. //
  4481. // Check to see if PDE is marked as LARGE_PAGE. If so,
  4482. // make it valid and install the large page size PTE.
  4483. // If not, branch to KiPageFault.
  4484. //
  4485. //
  4486. // Notes:
  4487. //
  4488. // PCR page mapped with TR
  4489. // --
  4490. HANDLER_ENTRY(KiPteNotPresentFault)
  4491. rva = h24 // passed
  4492. riha = h25 // passed
  4493. rpr = h26 // passed
  4494. rps = h27
  4495. rPfn = h28
  4496. rpAte = h28
  4497. rAte = h29
  4498. rAteEnd = h30
  4499. rAteBase = h31
  4500. rAteMask = h22
  4501. pIndr = pt1
  4502. mov rps = PS_4K << PS_SHIFT // M
  4503. movl rAteBase = ALT4KB_BASE // L
  4504. mov rAteMask = ATE_MASK0 // I
  4505. shr.u rPfn = rva, PAGE4K_SHIFT // I
  4506. ;;
  4507. shladd rpAte = rPfn, PTE_SHIFT, rAteBase // M
  4508. movl rAteEnd = ALT4KB_END // L
  4509. ;;
  4510. ld8.s rAte = [rpAte] // M
  4511. andcm rAteMask = -1, rAteMask // I
  4512. cmp.ltu pIndr = rpAte, rAteEnd // I
  4513. ;;
  4514. tnat.z.and pIndr = rAte // I
  4515. tbit.nz.and pIndr = rAte, PTE_VALID // I
  4516. or rAteMask = rAte, rAteMask // M
  4517. tbit.nz.and pIndr = rAte, PTE_ACCESS // I
  4518. tbit.nz.and pIndr = rAte, ATE_INDIRECT // I
  4519. (pIndr) br.cond.spnt KiPteIndirectFault
  4520. br.sptk KiPageFault // B
  4521. HANDLER_EXIT(KiPteNotPresentFault)
  4522. //
  4523. // ++
  4524. //
  4525. // Routine:
  4526. //
  4527. // KiKseg4Fault
  4528. //
  4529. // Description:
  4530. //
  4531. // TLB miss on KSEG4 space
  4532. //
  4533. //
  4534. // On entry:
  4535. //
  4536. // rva (h24) : faulting virtual address
  4537. // riha (h25) : IHA address
  4538. // rpr (h26) : saved predicate
  4539. //
  4540. // Process:
  4541. //
  4542. //
  4543. // Notes:
  4544. //
  4545. // PCR page mapped with TR
  4546. // --
  4547. HANDLER_ENTRY(KiKseg4Fault)
  4548. rIPSR = h22
  4549. rISR = h23
  4550. rva = h24 // passed
  4551. riha = h25
  4552. rpr = h26 // passed
  4553. rPte = h27
  4554. mov rISR = cr.isr // M
  4555. movl rPte = VALID_KERNEL_PTE | PTE_NOCACHE // L
  4556. mov rIPSR = cr.ipsr // M
  4557. shr.u rva = rva, PAGE_SHIFT // I
  4558. ;;
  4559. tbit.z pt2, pt3 = rISR, ISR_SP // I
  4560. dep.z rva = rva, PAGE_SHIFT, 32 // I
  4561. ;;
  4562. or rPte = rPte, rva // I
  4563. dep rIPSR = 1, rIPSR, PSR_ED, 1 // I
  4564. ;;
  4565. (pt2) itc.d rPte // M
  4566. ;;
  4567. (pt3) mov cr.ipsr = rIPSR // M
  4568. ;;
  4569. mov pr = rpr, -1 // I
  4570. rfi // B
  4571. ;;
  4572. HANDLER_EXIT(KiKseg4Fault)
  4573. //
  4574. // ++
  4575. //
  4576. // Routine:
  4577. //
  4578. // KiPageFault
  4579. //
  4580. // Description:
  4581. //
  4582. // This must be a genuine page fault. Call KiMemoryFault().
  4583. //
  4584. //
  4585. // On entry:
  4586. //
  4587. // rva (h24) : offending virtual address
  4588. // rpr (h26) : PDE contents
  4589. //
  4590. // Process:
  4591. //
  4592. // Restores the save predicate (pr), and branches to
  4593. // KiGenericExceptionHandler with the argument KiMemoryFault with
  4594. // macro VECTOR_CALL_HANDLER().
  4595. //
  4596. // Notes:
  4597. //
  4598. // PCR page mapped with TR
  4599. // --
  4600. HANDLER_ENTRY(KiPageFault)
  4601. rva = h24
  4602. rPSR_ED = h25
  4603. rpr = h26
  4604. rIPSR = h27
  4605. rps = h29
  4606. rCode = h30
  4607. rISR = h31
  4608. //
  4609. // check to see if a page fault occurred on a speculative load or
  4610. // lfetch.fault. if so, set IPSR.ed bit. This forces to generate a NaT on
  4611. // ld.s and steps out to the next instruction on lfetch.fault after
  4612. // rfi.
  4613. //
  4614. mov rISR = cr.isr // M
  4615. movl rPSR_ED = 1 << PSR_ED // L
  4616. mov rIPSR = cr.ipsr // M
  4617. ;;
  4618. and rCode = ISR_NA_CODE_MASK, rISR // A
  4619. or rIPSR = rIPSR, rPSR_ED // A
  4620. tbit.nz pt1, pt2 = rISR, ISR_NA // I
  4621. ;;
  4622. (pt1) cmp.ne pt0, p0 = ISR_LFETCH, rCode // A
  4623. (pt2) tbit.z pt0, p0 = rISR, ISR_SP // I
  4624. (pt0) br.cond.spnt KiCallMemoryFault // B
  4625. mov cr.ipsr = rIPSR // M
  4626. ;;
  4627. mov pr = rpr, -1 // I
  4628. rfi // B
  4629. ;;
  4630. KiCallMemoryFault:
  4631. mov rHIFA = cr.ifa
  4632. movl rHHandler = KiMemoryFault
  4633. mov rps = PAGE_SHIFT << PS_SHIFT
  4634. mov pr = rpr, -1 // I
  4635. ;;
  4636. ptc.l rHIFA, rps
  4637. br.sptk KiGenericExceptionHandler
  4638. HANDLER_EXIT(KiPageFault)
  4639. //
  4640. // ++
  4641. //
  4642. // Routine:
  4643. //
  4644. // KiPteIndirectFault
  4645. //
  4646. // Description:
  4647. //
  4648. // The PTE itself indicates a PteIndirect fault. The target PTE address
  4649. // should be generated by extracting PteOffset from PTE and adding it to
  4650. // PTE_UBASE. The owner field of the target PTE must be 1. Otherwise,
  4651. // Call MmX86Fault().
  4652. //
  4653. // On entry:
  4654. //
  4655. // rva (h24) : offending virtual address
  4656. // rpr (h26) : PDE contents
  4657. //
  4658. // Process:
  4659. //
  4660. // Restores the save predicate (pr), and branches to
  4661. // KiGenericExceptionHandler with the argument KiMemoryFault with
  4662. // macro VECTOR_CALL_HANDLER().
  4663. //
  4664. // Notes:
  4665. //
  4666. // PCR page mapped with TR
  4667. // --
  4668. HANDLER_ENTRY(KiPteIndirectFault)
  4669. rpr = h26 // passed
  4670. rps = h27 // passed
  4671. rpAte = h28 // passed
  4672. rAte = h29 // passed
  4673. rPte = h30
  4674. rPte0 = h31
  4675. rAteMask = h22 // passed
  4676. rVa12 = h23
  4677. rPteOffset = h23
  4678. rpNewPte = h21
  4679. rOldIIP = h17 // preserved
  4680. rIA32IIP = h18
  4681. rpVa = h19 // preserved
  4682. rIndex = h20 // preserved
  4683. rpBuffer= h16
  4684. rpPte = h22
  4685. pBr = pt0
  4686. pPrg = pt3
  4687. pLoop = pt4
  4688. pClear = pt5
  4689. mov cr.itir = rps // M
  4690. thash rpNewPte = r0 // M
  4691. mov rIA32IIP = cr.iip // M
  4692. extr.u rPteOffset = rAte, PAGE4K_SHIFT, 32 // I
  4693. ;;
  4694. add rpNewPte = rPteOffset, rpNewPte // M/I
  4695. cmp.eq pLoop, pClear = rIA32IIP, rOldIIP // I
  4696. ;;
  4697. ld8.s rPte = [rpNewPte] // M
  4698. shr rVa12 = rpAte, PTE_SHIFT // I
  4699. ;;
  4700. tnat.nz.or pBr = rPte // I
  4701. tbit.z.or pBr = rPte, PTE_VALID // I
  4702. tbit.z.or pBr = rPte, PTE_ACCESS // I
  4703. (pBr) br.cond.spnt KiPageFault
  4704. ;;
  4705. (pClear)mov rIndex = 0 // M
  4706. and rPte0 = rPte, rAteMask // I
  4707. ;;
  4708. #if 1
  4709. //
  4710. // try to acquire the spinlock
  4711. // if failed, resume execution and try again on the next fault
  4712. //
  4713. mov rpVa = 1
  4714. movl rpBuffer = KiPcr + PcFpbLock // L
  4715. ;;
  4716. xchg8 rpVa = [rpBuffer], rpVa
  4717. ;;
  4718. cmp.ne pt1 = 0, rpVa
  4719. (pt1) br.cond.spnt Kpif10
  4720. ;;
  4721. #endif
  4722. //
  4723. // deposit extra PFN bits for 4k page
  4724. //
  4725. dep rPte0 = rVa12, rPte0, PAGE4K_SHIFT, PAGE_SHIFT-PAGE4K_SHIFT // I
  4726. ;;
  4727. (pClear)itc.d rPte0 // M
  4728. ;;
  4729. and rIndex = 7, rIndex // A
  4730. movl rpBuffer = KiPcr + PcForwardProgressBuffer // L
  4731. ;;
  4732. shladd rpVa = rIndex, 4, rpBuffer // M
  4733. add rIndex = 1, rIndex // I
  4734. ;;
  4735. st8 [rpVa] = rva // M
  4736. add rpPte = 8, rpVa // I
  4737. ;;
  4738. st8 [rpPte] = rPte0 // M
  4739. #if 1
  4740. //
  4741. // done updating the forward progress buffer entry, release spinlock
  4742. //
  4743. movl rpBuffer = KiPcr + PcFpbLock // L
  4744. ;;
  4745. st8.rel [rpBuffer] = r0, PcForwardProgressBuffer - PcFpbLock
  4746. #endif
  4747. mov rOldIIP = rIA32IIP // I
  4748. #if !defined(NT_UP)
  4749. rAte2 = h28
  4750. rPte2 = h31
  4751. ld8.s rPte2 = [rpNewPte] // M
  4752. ld8.s rAte2 = [rpAte] // M
  4753. cmp.ne pPrg = zero, zero // I
  4754. ;;
  4755. cmp.ne.or pPrg = rPte, rPte2 // I
  4756. tnat.nz.or pPrg = rPte2 // I
  4757. cmp.ne.or pPrg = rAte, rAte2 // I
  4758. tnat.nz.or pPrg = rAte2 // I
  4759. ;;
  4760. (pPrg) ptc.l rva, rps // M
  4761. (pPrg) st8 [rpPte] = r0 // M
  4762. #endif
  4763. (pLoop) br.cond.spnt KiFillForwardProgressTb // B
  4764. Kpif10:
  4765. mov pr = rpr, -1 // I
  4766. rfi;; // B
  4767. HANDLER_EXIT(KiPteIndirectFault)
  4768. //
  4769. // ++
  4770. //
  4771. // Routine:
  4772. //
  4773. // Ki4KDataTlbFault
  4774. //
  4775. // Description:
  4776. //
  4777. // Branched from KiDataTlbVector if PTE.Cache indicates the reserved
  4778. // encoding. Reads the corresponding ATE and creates a 4kb TB on the
  4779. // fly inserts it to the TLB. If a looping condition at IIP is
  4780. // detected, it branches to KiFillForwardProgressTb and insert the TBs
  4781. // from the forward progress TB queue.
  4782. //
  4783. // On entry:
  4784. //
  4785. // rva (h24) : offending virtual address
  4786. // riha(h25) : IHA address
  4787. // rpr (h26) : PDE contents
  4788. //
  4789. // Notes:
  4790. //
  4791. // --
  4792. HANDLER_ENTRY(Ki4KDataTlbFault)
  4793. rva = h24 // passed
  4794. riha = h25 // passed
  4795. rpr = h26 // passed
  4796. rps = h27
  4797. rPfn = h28
  4798. rpAte = h28
  4799. rAte = h29
  4800. rPte = h30
  4801. rAltBase = h31
  4802. rPte0 = h31
  4803. rAteMask = h22
  4804. rVa12 = h23
  4805. rOldIIP = h17 // preserved
  4806. rIA32IIP = h18
  4807. rpVa = h19
  4808. rIndex = h20 // preserved
  4809. rpBuffer= h16
  4810. rpPte = h21
  4811. pBr = pt0
  4812. pIndr = pt1
  4813. pMiss = pt2
  4814. pPrg = pt3
  4815. pLoop = pt4
  4816. pClear = pt5
  4817. pMiss2 = pt6
  4818. mov rIA32IIP = cr.iip // M
  4819. mov rps = PS_4K << PS_SHIFT // I
  4820. dep rAteMask = 1, r0, 32, 1 // Set rAteMask equal to 2**32
  4821. ;;
  4822. cmp.ge pBr, pt7 = rva, rAteMask // M/I, Test to see if rva is out of bounds.
  4823. movl rAltBase = ALT4KB_BASE // L
  4824. ld8.s rPte = [riha] // M
  4825. shr.u rPfn = rva, PAGE4K_SHIFT // I
  4826. ;;
  4827. shladd rpAte = rPfn, PTE_SHIFT, rAltBase // I
  4828. ;;
  4829. ld8.s rAte = [rpAte] // M
  4830. movl rAteMask = ATE_MASK // L
  4831. ;;
  4832. cmp.eq pLoop, pClear = rIA32IIP, rOldIIP// M
  4833. tnat.nz pMiss = rPte // I
  4834. (pMiss) br.cond.spnt KiPageTableFault // B
  4835. (pt7) tnat.nz pMiss2 = rAte // I
  4836. (pMiss2)br.cond.spnt KiAltTableFault // B
  4837. tbit.z.or pBr = rPte, PTE_VALID // I
  4838. tbit.z.or pBr = rAte, PTE_VALID // I
  4839. tbit.z.or pBr = rAte, PTE_ACCESS // I
  4840. or rAteMask = rAte, rAteMask // M
  4841. tbit.nz pIndr, p0 = rAte, ATE_INDIRECT // I
  4842. (pBr) br.cond.spnt KiPageFault // B
  4843. dep rPte0 = 0, rPte, 2, 3 // I, make it WB
  4844. shr rVa12 = rpAte, PTE_SHIFT // I
  4845. (pIndr) br.cond.spnt KiPteIndirectFault // B
  4846. ;;
  4847. (pClear)mov rIndex = 0 // M
  4848. mov cr.itir = rps // M
  4849. and rPte0 = rPte0, rAteMask // I
  4850. ;;
  4851. #if 1
  4852. //
  4853. // try to acquire the spinlock
  4854. // if failed, resume execution and try again on the next fault
  4855. //
  4856. mov rpVa = 1
  4857. movl rpBuffer = KiPcr + PcFpbLock // L
  4858. ;;
  4859. xchg8 rpVa = [rpBuffer], rpVa
  4860. ;;
  4861. cmp.ne pt1 = 0, rpVa
  4862. (pt1) br.cond.spnt K4dtf10
  4863. ;;
  4864. #endif
  4865. //
  4866. // deposit extra PFN bits for 4k page
  4867. //
  4868. dep rPte0 = rVa12, rPte0, PAGE4K_SHIFT, PAGE_SHIFT-PAGE4K_SHIFT // I
  4869. ;;
  4870. (pClear)itc.d rPte0 // M, install PTE
  4871. ;;
  4872. and rIndex = 7, rIndex // A
  4873. movl rpBuffer = KiPcr + PcForwardProgressBuffer // L
  4874. ;;
  4875. shladd rpVa = rIndex, 4, rpBuffer // M
  4876. add rIndex = 1, rIndex // I
  4877. ;;
  4878. st8 [rpVa] = rva // M
  4879. add rpPte = 8, rpVa // I
  4880. ;;
  4881. st8 [rpPte] = rPte0 // M
  4882. //
  4883. // done updating the forward progress buffer entry, release spinlock
  4884. //
  4885. movl rpBuffer = KiPcr + PcFpbLock // L
  4886. ;;
  4887. st8.rel [rpBuffer] = r0, PcForwardProgressBuffer - PcFpbLock
  4888. mov rOldIIP = rIA32IIP // I
  4889. #if !defined(NT_UP)
  4890. rps = h27
  4891. rAte2 = h28
  4892. rPte2 = h31
  4893. ld8.s rPte2 = [riha] // M
  4894. ld8.s rAte2 = [rpAte] // M
  4895. cmp.ne pPrg = zero, zero // I
  4896. ;;
  4897. cmp.ne.or pPrg = rPte, rPte2 // M
  4898. tnat.nz.or pPrg = rPte2 // I
  4899. cmp.ne.or pPrg = rAte, rAte2 // M
  4900. tnat.nz.or pPrg = rAte2 // I
  4901. ;;
  4902. (pPrg) ptc.l rva, rps // M
  4903. (pPrg) st8 [rpPte] = r0 // M
  4904. #endif
  4905. (pLoop) br.cond.spnt KiFillForwardProgressTb // B
  4906. K4dtf10:
  4907. mov pr = rpr, -1 // I
  4908. rfi;; // B
  4909. HANDLER_EXIT(Ki4KDataTlbFault)
  4910. //
  4911. // ++
  4912. //
  4913. // Routine:
  4914. //
  4915. // Ki4KInstTlbFault
  4916. //
  4917. // Description:
  4918. //
  4919. // Branched from KiInstTlbVector if PTE.Cache indicates the reserved
  4920. // encoding. Reads the corresponding ATE and creates a 4kb TB on the
  4921. // fly inserts it to the TLB.
  4922. //
  4923. // On entry:
  4924. //
  4925. // rva (h24) : offending virtual address
  4926. // riha(h25) : IHA address
  4927. // rpr (h26) : PDE contents
  4928. //
  4929. // Notes:
  4930. //
  4931. // --
  4932. HANDLER_ENTRY(Ki4KInstTlbFault)
  4933. rva = h24 // passed
  4934. riha = h25 // passed
  4935. rpr = h26 // passed
  4936. rps = h27
  4937. rPfn = h28
  4938. rpAte = h28
  4939. rAte = h29
  4940. rPte = h30
  4941. rAltBase = h31
  4942. rPte0 = h31
  4943. rAteMask = h22
  4944. rVa12 = h23
  4945. pBr = pt0
  4946. pIndr = pt1
  4947. pMiss = pt2
  4948. pPrg = pt3
  4949. pMiss2 = pt6
  4950. mov rps = PS_4K << PS_SHIFT // M
  4951. movl rAltBase = ALT4KB_BASE // L
  4952. shr.u rPfn = rva, PAGE4K_SHIFT // I
  4953. dep rAteMask = 1, r0, 32, 1 // Set rAteMask equal to 2**32
  4954. ;;
  4955. ld8.s rPte = [riha] // M
  4956. cmp.ge pBr, pt7 = rva, rAteMask // M/I, Test to see if rva is out of bounds.
  4957. shladd rpAte = rPfn, PTE_SHIFT, rAltBase // I
  4958. ;;
  4959. ld8.s rAte = [rpAte] // M
  4960. movl rAteMask = ATE_MASK // L
  4961. ;;
  4962. tnat.nz pMiss = rPte // I
  4963. (pMiss) br.cond.spnt KiPageTableFault // B
  4964. (pt7) tnat.nz pMiss2 = rAte // I
  4965. (pMiss2)br.cond.spnt KiAltTableFault // B
  4966. tbit.z.or pBr = rPte, PTE_VALID // I
  4967. tbit.z.or pBr = rAte, PTE_VALID // I
  4968. tbit.z.or pBr = rAte, PTE_ACCESS // I
  4969. or rAteMask = rAte, rAteMask // M
  4970. tbit.nz pIndr, p0 = rAte, ATE_INDIRECT // I
  4971. (pBr) br.cond.spnt KiPageFault // B
  4972. dep rPte0 = 0, rPte, 2, 3 // I, make it WB
  4973. shr rVa12 = rpAte, PTE_SHIFT // I
  4974. (pIndr) br.cond.spnt KiPteIndirectFault // B
  4975. ;;
  4976. mov cr.itir = rps // M
  4977. and rPte0 = rPte0, rAteMask // I
  4978. ;;
  4979. //
  4980. // deposit extra PFN bits for 4k page
  4981. //
  4982. dep rPte0 = rVa12, rPte0, PAGE4K_SHIFT, PAGE_SHIFT-PAGE4K_SHIFT // I
  4983. ;;
  4984. itc.i rPte0 // M, install PTE
  4985. ;;
  4986. #if !defined(NT_UP)
  4987. rps = h27
  4988. rAte2 = h28
  4989. rPte2 = h31
  4990. ld8.s rPte2 = [riha] // M
  4991. ld8.s rAte2 = [rpAte] // M
  4992. cmp.ne pPrg = zero, zero // I
  4993. ;;
  4994. cmp.ne.or pPrg = rPte, rPte2 // M
  4995. tnat.nz.or pPrg = rPte2 // I
  4996. cmp.ne.or pPrg = rAte, rAte2 // M
  4997. tnat.nz.or pPrg = rAte2 // I
  4998. ;;
  4999. (pPrg) ptc.l rva, rps // M
  5000. #endif
  5001. mov pr = rpr, -1 // I
  5002. rfi;; // B
  5003. HANDLER_EXIT(Ki4KInstTlbFault)
  5004. //
  5005. // ++
  5006. //
  5007. // Routine:
  5008. //
  5009. // KiAltTableFault
  5010. //
  5011. // Description:
  5012. //
  5013. // Branched from Inst/DataAccessBitVector
  5014. // Inserts a missing PTE translation for the alt table.
  5015. //
  5016. // On entry:
  5017. //
  5018. // rva (h24) : offending virtual address
  5019. // riha (h25) : a offending PTE address
  5020. // rpr: (h26) : saved predicate
  5021. //
  5022. // Handle:
  5023. //
  5024. // --
  5025. HANDLER_ENTRY(KiAltTableFault)
  5026. rpAte = h28 // passed
  5027. rva = h24
  5028. riha = h25
  5029. rpr = h26 // passed
  5030. rPte = h27
  5031. rPte2 = h28
  5032. rps = h29
  5033. thash riha = rpAte // M
  5034. cmp.ne pt1 = r0, r0
  5035. mov rva = rpAte // I
  5036. ;;
  5037. ld8.s rPte = [riha] // M
  5038. ;;
  5039. tnat.nz pt0, p0 = rPte // I
  5040. tbit.z.or pt1, p0 = rPte, PTE_ACCESS
  5041. tbit.z.or pt1, p0 = rPte, PTE_VALID // I, if non-present page fault
  5042. (pt0) br.cond.spnt KiPageTableFault // B
  5043. (pt1) br.cond.spnt KiPteNotPresentFault // B
  5044. ;;
  5045. mov cr.ifa = rva
  5046. ;;
  5047. itc.d rPte // M
  5048. ;;
  5049. #if !defined(NT_UP)
  5050. ld8.s rPte2 = [riha] // M
  5051. mov rps = PAGE_SHIFT << PS_SHIFT // I
  5052. cmp.ne pt0 = zero, zero // I
  5053. ;;
  5054. cmp.ne.or pt0 = rPte2, rPte // M
  5055. tnat.nz.or pt0 = rPte2 // I
  5056. ;;
  5057. (pt0) ptc.l rva, rps // M
  5058. #endif
  5059. mov pr = rpr, -1 // I
  5060. rfi;; // B
  5061. HANDLER_EXIT(KiAltTableFault)
  5062. //
  5063. // ++
  5064. //
  5065. // Routine:
  5066. //
  5067. // KiFillForwardProgressTb
  5068. //
  5069. // Description:
  5070. //
  5071. // Fill TB from TLB forward progress buffer.
  5072. //
  5073. // On entry:
  5074. //
  5075. // rpBuffer (h16) : forward progress buffer address
  5076. // rpr: (h26) : saved predicate
  5077. //
  5078. // Handle:
  5079. //
  5080. // --
  5081. HANDLER_ENTRY(KiFillForwardProgressTb)
  5082. rLc = h29
  5083. rT0 = h28
  5084. rps = h27
  5085. rpr = h26
  5086. rVa = h22
  5087. rPte = h21
  5088. rpVa = h19
  5089. rpPte = h17
  5090. rpBuffer= h16
  5091. mov rpVa = rpBuffer // A
  5092. mov.i rLc = ar.lc // I
  5093. mov rT0 = NUMBER_OF_FWP_ENTRIES - 1 //
  5094. ;;
  5095. add rpPte = 8, rpBuffer // A
  5096. mov.i ar.lc = rT0 // I
  5097. ;;
  5098. fpb_loop:
  5099. //
  5100. // use ALAT to see if somebody modify the PTE entry
  5101. //
  5102. ld8 rVa = [rpVa], 16 // M
  5103. ld8.a rPte = [rpPte] // M
  5104. ;;
  5105. mov cr.ifa = rVa // M
  5106. cmp.ne pt0, pt1 = rPte, r0 // I
  5107. ;;
  5108. (pt0) itc.d rPte // M
  5109. ;;
  5110. (pt0) ld8.c.clr rPte = [rpPte] // M
  5111. add rpPte = 16, rpPte // I
  5112. ;;
  5113. (pt1) invala.e rPte // M, invalidate ALAT entry
  5114. (pt0) cmp.eq.and pt0 = rPte, r0 // I
  5115. ;;
  5116. (pt0) ptc.l rVa, rps // M
  5117. br.cloop.dptk.many fpb_loop;; // B
  5118. mov.i ar.lc = rLc
  5119. mov pr = rpr, -1 // I
  5120. rfi // B
  5121. ;;
  5122. //
  5123. // Add four nop cycles (two bundles) bundles of NOP's to
  5124. // workaround McKinly Errata.
  5125. //
  5126. nop.m 0
  5127. ;;
  5128. nop.m 0
  5129. ;;
  5130. nop.m 0
  5131. ;;
  5132. nop.m 0
  5133. ;;
  5134. HANDLER_EXIT(KiFillForwardProgressTb)
  5135. //++
  5136. //
  5137. // Routine Description:
  5138. //
  5139. // This routine begins the common code for raising an exception.
  5140. // The routine saves the non-volatile state and dispatches to the
  5141. // next level exception dispatcher.
  5142. //
  5143. // Arguments:
  5144. //
  5145. // a0 - pointer to trap frame
  5146. // a1 - previous mode
  5147. //
  5148. // Return Value:
  5149. //
  5150. // None.
  5151. //
  5152. //--
  5153. NESTED_ENTRY(KiExceptionDispatch)
  5154. //
  5155. // Build exception frame
  5156. //
  5157. .regstk 2, 3, 5, 0
  5158. .prologue 0xA, loc0
  5159. alloc t16 = ar.pfs, 2, 3, 5, 0
  5160. mov loc0 = sp
  5161. cmp4.eq pt0 = UserMode, a1 // previous mode is user?
  5162. mov loc1 = brp
  5163. .fframe ExceptionFrameLength
  5164. add sp = -ExceptionFrameLength, sp
  5165. ;;
  5166. .save ar.unat, loc2
  5167. mov loc2 = ar.unat
  5168. add t0 = ExFltS19+STACK_SCRATCH_AREA, sp
  5169. add t1 = ExFltS18+STACK_SCRATCH_AREA, sp
  5170. ;;
  5171. .save.gf 0x0, 0xC0000
  5172. stf.spill [t0] = fs19, ExFltS17-ExFltS19
  5173. stf.spill [t1] = fs18, ExFltS16-ExFltS18
  5174. ;;
  5175. .save.gf 0x0, 0x30000
  5176. stf.spill [t0] = fs17, ExFltS15-ExFltS17
  5177. stf.spill [t1] = fs16, ExFltS14-ExFltS16
  5178. mov t10 = bs4
  5179. ;;
  5180. .save.gf 0x0, 0xC000
  5181. stf.spill [t0] = fs15, ExFltS13-ExFltS15
  5182. stf.spill [t1] = fs14, ExFltS12-ExFltS14
  5183. mov t11 = bs3
  5184. ;;
  5185. .save.gf 0x0, 0x3000
  5186. stf.spill [t0] = fs13, ExFltS11-ExFltS13
  5187. stf.spill [t1] = fs12, ExFltS10-ExFltS12
  5188. mov t12 = bs2
  5189. ;;
  5190. .save.gf 0x0, 0xC00
  5191. stf.spill [t0] = fs11, ExFltS9-ExFltS11
  5192. stf.spill [t1] = fs10, ExFltS8-ExFltS10
  5193. mov t13 = bs1
  5194. ;;
  5195. .save.gf 0x0, 0x300
  5196. stf.spill [t0] = fs9, ExFltS7-ExFltS9
  5197. stf.spill [t1] = fs8, ExFltS6-ExFltS8
  5198. mov t14 = bs0
  5199. ;;
  5200. .save.gf 0x0, 0xC0
  5201. stf.spill [t0] = fs7, ExFltS5-ExFltS7
  5202. stf.spill [t1] = fs6, ExFltS4-ExFltS6
  5203. mov t15 = ar.lc
  5204. ;;
  5205. .save.gf 0x0, 0x30
  5206. stf.spill [t0] = fs5, ExFltS3-ExFltS5
  5207. stf.spill [t1] = fs4, ExFltS2-ExFltS4
  5208. ;;
  5209. .save.f 0xC
  5210. stf.spill [t0] = fs3, ExFltS1-ExFltS3 // save fs3
  5211. stf.spill [t1] = fs2, ExFltS0-ExFltS2 // save fs2
  5212. ;;
  5213. .save.f 0x3
  5214. stf.spill [t0] = fs1, ExBrS4-ExFltS1 // save fs1
  5215. stf.spill [t1] = fs0, ExBrS3-ExFltS0 // save fs0
  5216. ;;
  5217. .save.b 0x18
  5218. st8 [t0] = t10, ExBrS2-ExBrS4 // save bs4
  5219. st8 [t1] = t11, ExBrS1-ExBrS3 // save bs3
  5220. ;;
  5221. .save.b 0x6
  5222. st8 [t0] = t12, ExBrS0-ExBrS2 // save bs2
  5223. st8 [t1] = t13, ExIntS2-ExBrS1 // save bs1
  5224. ;;
  5225. .save.b 0x1
  5226. st8 [t0] = t14, ExIntS3-ExBrS0 // save bs0
  5227. movl out0 = KiPcr+PcCurrentThread
  5228. ;;
  5229. .save.gf 0xC, 0x0
  5230. .mem.offset 0,0
  5231. st8.spill [t0] = s3, ExIntS1-ExIntS3 // save s3
  5232. .mem.offset 8,0
  5233. st8.spill [t1] = s2, ExIntS0-ExIntS2 // save s2
  5234. ;;
  5235. .save.gf 0x3, 0x0
  5236. .mem.offset 0,0
  5237. st8.spill [t0] = s1, ExApLC-ExIntS1 // save s1
  5238. .mem.offset 8,0
  5239. st8.spill [t1] = s0, ExApEC-ExIntS0 // save s0
  5240. ;;
  5241. .savepsp ar.pfs, ExceptionFrameLength-ExApEC-STACK_SCRATCH_AREA
  5242. st8 [t1] = t16, ExIntNats-ExApEC
  5243. mov t4 = ar.unat // captured Nats of s0-s3
  5244. ;;
  5245. (pt0) ld8 out0 = [out0]
  5246. ;;
  5247. (pt0) add out0 = ThStackBase, out0
  5248. .savepsp ar.lc, ExceptionFrameLength-ExApLC-STACK_SCRATCH_AREA
  5249. st8 [t0] = t15
  5250. .savepsp @priunat, ExceptionFrameLength-ExIntNats-STACK_SCRATCH_AREA
  5251. st8 [t1] = t4 // save Nats of s0-s3
  5252. ;;
  5253. PROLOGUE_END
  5254. (pt0) ld8 out0 = [out0]
  5255. ;;
  5256. (pt0) add out0 = -ThreadStateSaveAreaLength+TsHigherFPVolatile, out0
  5257. (pt0) br.call.sptk brp = KiSaveHigherFPVolatile
  5258. ;;
  5259. CAPSTART(KiExceptionDispatch,KiDispatchException)
  5260. add out0 = TrExceptionRecord, a0 // -> exception record
  5261. add out1 = STACK_SCRATCH_AREA, sp // -> exception frame
  5262. mov out2 = a0 // -> trap frame
  5263. mov out3 = a1 // previous mode
  5264. mov out4 = 1 // first chance
  5265. br.call.sptk.many brp = KiDispatchException
  5266. ;;
  5267. CAPEND(KiExceptionDispatch)
  5268. add t1 = ExApEC+STACK_SCRATCH_AREA, sp
  5269. movl t0 = KiExceptionExit
  5270. ;;
  5271. //
  5272. // Interrupts must be disabled before calling KiExceptionExit
  5273. // because the unwind code cannot unwind from that point.
  5274. //
  5275. FAST_DISABLE_INTERRUPTS
  5276. ld8 t1 = [t1]
  5277. mov brp = t0
  5278. ;;
  5279. mov ar.unat = loc2
  5280. mov ar.pfs = t1
  5281. add s1 = STACK_SCRATCH_AREA, sp // s1 -> exception frame
  5282. mov s0 = a0 // s0 -> trap frame
  5283. br.ret.sptk brp
  5284. ;;
  5285. NESTED_EXIT(KiExceptionDispatch)
  5286. //++
  5287. //
  5288. // BOOLEAN
  5289. // KeInvalidAccessAllowed (
  5290. // IN PVOID TrapInformation
  5291. // )
  5292. //
  5293. // Routine Description:
  5294. //
  5295. // Mm will pass a pointer to a trap frame prior to issuing a bug check on
  5296. // a pagefault. This routine lets Mm know if it is ok to bugcheck. The
  5297. // specific case we must protect are the interlocked pop sequences which can
  5298. // blindly access memory that may have been freed and/or reused prior to the
  5299. // access. We don't want to bugcheck the system in these cases, so we check
  5300. // the instruction pointer here.
  5301. //
  5302. // Arguments:
  5303. //
  5304. // TrapFrame (a0) - Supplies a trap frame pointer. NULL means return False.
  5305. //
  5306. // Return Value:
  5307. //
  5308. // True if the invalid access should be ignored.
  5309. // False which will usually trigger a bugcheck.
  5310. //
  5311. //--
  5312. LEAF_ENTRY(KeInvalidAccessAllowed)
  5313. .regstk 1, 0, 0, 0
  5314. cmp.eq pt0 = 0, a0
  5315. movl t1 = ExpInterlockedPopEntrySListFault
  5316. add t0 = TrStIIP, a0
  5317. mov v0 = zero // assume access not allowed
  5318. (pt0) br.ret.spnt brp
  5319. ;;
  5320. ld8 t0 = [t0]
  5321. ;;
  5322. cmp.eq pt2 = t0, t1
  5323. ;;
  5324. nop.m 0
  5325. (pt2) mov v0 = 1
  5326. br.ret.sptk brp
  5327. LEAF_EXIT(KeInvalidAccessAllowed)
  5328. LEAF_ENTRY(KeScrubBackingStoreRegisters)
  5329. .regstk 1, 15, 1, 0
  5330. alloc loc0 = 1, 15, 1, 0
  5331. mov loc1 = brp
  5332. cmp.ge pt0, pt1 = 17, a0
  5333. add out0 = -16, a0
  5334. mov loc2 = r0
  5335. mov loc3 = r0
  5336. ;;
  5337. mov loc4 = r0
  5338. mov loc5 = r0
  5339. mov loc6 = r0
  5340. mov loc7 = r0
  5341. mov loc8 = r0
  5342. mov loc9 = r0
  5343. mov loc10 = r0
  5344. mov loc11 = r0
  5345. mov loc12 = r0
  5346. mov loc13 = r0
  5347. mov loc14 = r0
  5348. (pt1) br.call.dpnt brp = KeScrubBackingStoreRegisters
  5349. mov out0 = r0
  5350. mov brp = loc1
  5351. mov loc1 = r0
  5352. mov a0 = r0
  5353. mov ar.pfs = loc0
  5354. mov loc0 = r0
  5355. br.ret.sptk brp
  5356. LEAF_EXIT (KeScrubBackingStoreRegisters)
  5357. LEAF_ENTRY(KiPageZeroFault)
  5358. rpr = h26
  5359. rK5 = h28
  5360. mov h29 = cr.ipsr
  5361. tbit.z pt1, pt0 = rK5, 0
  5362. ;;
  5363. dep h29 = 1, h29, PSR_ED, 1 // I
  5364. (pt0) itc.d r0
  5365. ;;
  5366. mov cr.ipsr = h29
  5367. (pt0) mov rK5 = r0
  5368. (pt1) add rK5 = 3, rK5
  5369. ;;
  5370. mov ar.k5 = rK5
  5371. mov pr = rpr, -1 // I
  5372. rfi;; // B
  5373. LEAF_EXIT(KiPageZeroFault)