Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1235 lines
28 KiB

  1. //++
  2. //
  3. // Module Name:
  4. //
  5. // miscs.s
  6. //
  7. // Abstract:
  8. //
  9. // This module implements machine dependent miscellaneous kernel functions.
  10. // Functions are provided to request a software interrupt, continue thread
  11. // execution, flush TLBs and write buffers, and perform last chance
  12. // exception processing.
  13. //
  14. // Author:
  15. //
  16. // William K. Cheung (wcheung) 3-Nov-1995
  17. //
  18. // Environment:
  19. //
  20. // Kernel mode only.
  21. //
  22. // Revision History:
  23. //
  24. // 7-Jul-1997 bl Updated to EAS2.3
  25. //
  26. // 27-Feb-1996 wc Updated to EAS2.1
  27. //
  28. // 11-Jan-1996 wc Set up register sp to point to the exception frame
  29. // on the stack before calling KiSaveExceptionFrame and
  30. // branching directly to KiExceptionExit.
  31. //
  32. //--
  33. #include "ksia64.h"
  34. //
  35. // Global symbols
  36. //
  37. PublicFunction(KiContinue)
  38. PublicFunction(KiSaveExceptionFrame)
  39. PublicFunction(KeTestAlertThread)
  40. PublicFunction(KiExceptionExit)
  41. PublicFunction(KiRaiseException)
  42. PublicFunction(KiLoadKernelDebugRegisters)
  43. PublicFunction(KeIsExecutingDpc)
  44. //
  45. //++
  46. //
  47. // NTSTATUS
  48. // NtContinue (
  49. // IN PCONTEXT ContextRecord,
  50. // IN BOOLEAN TestAlert
  51. // )
  52. //
  53. // Routine Description:
  54. //
  55. // This routine is called as a system service to continue execution after
  56. // an exception has occurred. Its functions is to transfer information from
  57. // the specified context record into the trap frame that was built when the
  58. // system service was executed, and then exit the system as if an exception
  59. // had occurred.
  60. //
  61. // Arguments:
  62. //
  63. // ContextRecord (a0) - Supplies a pointer to a context record.
  64. //
  65. // TestAlert (a1) - Supplies a boolean value that specifies whether alert
  66. // should be tested for the previous processor mode.
  67. //
  68. // N.B. Register t0 is assumed to contain the address of a trap frame.
  69. //
  70. // Return Value:
  71. //
  72. // Normally there is no return from this routine. However, if the specified
  73. // context record is misaligned or is not accessible, then the appropriate
  74. // status code is returned.
  75. //
  76. //--
  77. NESTED_ENTRY(NtContinue)
  78. NESTED_SETUP(2,4,3,0)
  79. .fframe ExceptionFrameLength
  80. add sp = -ExceptionFrameLength, sp
  81. PROLOGUE_END
  82. //
  83. // Transfer information from the context record to the exception and trap
  84. // frames.
  85. //
  86. // N.B. Must zero the loadrs bit-field of Context->RsRSC
  87. //
  88. add t1 = TrStIPSR, t0 // -> TrapFrame->StIPSR
  89. mov loc2 = t0
  90. ;;
  91. ld8 loc3 = [t1] // load TrapFrame->StIPSR
  92. mov out0 = a0 // context frame address
  93. ;;
  94. add out1 = STACK_SCRATCH_AREA, sp // -> exception frame
  95. mov out2 = t0 // trap frame address
  96. br.call.sptk.many brp = KiContinue
  97. ;;
  98. //
  99. // If KiContinue() returns success, then exit via the exception exit code.
  100. // Otherwise, return to the system service dispatcher.
  101. //
  102. // Check to determine if alert should be tested for the previous processor
  103. // mode and restore the previous mode in the thread object.
  104. //
  105. // Application that invokes the NtContinue() system service must have
  106. // flushed all stacked registers to the backing store. Sanitize the
  107. // bspstore to be equal to bsp; otherwise, some stacked GRs will not be
  108. // restored from the backing store.
  109. //
  110. add t0 = TrStIPSR, loc2
  111. movl t7 = 1 << PSR_TB | 1 << PSR_DB | 1 << PSR_SS | 1 << PSR_PP
  112. ;;
  113. ld8 t8 = [t0]
  114. cmp.ne pt0 = zero, v0 // if ne, transfer failed.
  115. ;;
  116. (pt0) dep t7 = 1, t7, PSR_LP, 1 // capture psr.lp if failed
  117. ;;
  118. add t2 = TrTrapFrame, loc2
  119. andcm t8 = t8, t7 // Clear old values
  120. and loc3 = t7, loc3 // capture psr.tb, db, ss, pp
  121. ;;
  122. or t8 = loc3, t8
  123. ;;
  124. st8 [t0] = t8
  125. add t3 = TrRsRSC, loc2
  126. (pt0) br.cond.spnt Nc10 // jump to Nc10 if pt0 is TRUE
  127. ;;
  128. //
  129. // Restore the nonvolatile machine state from the exception frame
  130. // and exit the system via the exception exit code.
  131. //
  132. ld8 t5 = [t2] // get old trap frame address
  133. movl t1 = KiPcr + PcCurrentThread // -> current thread
  134. ;;
  135. ld8 t0 = [t3], TrPreviousMode-TrRsRSC // load TrapFrame->RsRSC
  136. ld8 t4 = [t1] // get current thread address
  137. cmp4.ne pt1 = zero, a1 // if ne, test for alert
  138. ;;
  139. ld4 t6 = [t3], TrRsRSC-TrPreviousMode // get old previous mode
  140. dep t0 = r0, t0, RSC_MBZ1, RSC_LOADRS_LEN // zero preload field
  141. add t7 = ThPreviousMode, t4
  142. ;;
  143. (pt1) ld1 out0 = [t7] // get current previous mode
  144. st8 [t3] = t0 // save TrapFrame->RsRSC
  145. add t8 = ThTrapFrame, t4
  146. ;;
  147. st8 [t8] = t5 // restore old trap frame addr
  148. st1 [t7] = t6 // restore old previous mode
  149. (pt1) br.call.spnt.many brp = KeTestAlertThread
  150. ;;
  151. //
  152. // sp -> stack scratch area/FP save area/exception frame/trap frame
  153. //
  154. // Set up for branch to KiExceptionExit
  155. //
  156. // s0 = trap frame
  157. // s1 = exception frame
  158. //
  159. // N.B. predicate register alias pUstk & pKstk must be the same as trap.s
  160. // and they must be set up correctly upon entry into KiExceptionExit.
  161. //
  162. // N.B. The exception exit code will restore the exception frame & trap frame
  163. // and then rfi to user code. pUstk is set to 1 while pKstk is set to 0.
  164. //
  165. pUstk = ps3
  166. pKstk = ps4
  167. //
  168. // Interrupts must be disabled before calling KiExceptionExit
  169. // because the unwind code cannot unwind from that point.
  170. //
  171. FAST_DISABLE_INTERRUPTS
  172. cmp.eq pUstk, pKstk = zero, zero
  173. add s1 = STACK_SCRATCH_AREA, sp
  174. mov s0 = loc2
  175. br KiExceptionExit
  176. Nc10:
  177. .restore
  178. add sp = ExceptionFrameLength, sp
  179. NESTED_RETURN
  180. NESTED_EXIT(NtContinue)
  181. //++
  182. //
  183. // NTSTATUS
  184. // NtRaiseException (
  185. // IN PEXCEPTION_RECORD ExceptionRecord,
  186. // IN PCONTEXT ContextRecord,
  187. // IN BOOLEAN FirstChance
  188. // )
  189. //
  190. // Routine Description:
  191. //
  192. // This routine is called as a system service to raise an exception.
  193. // The exception can be raised as a first or second chance exception.
  194. //
  195. // Arguments:
  196. //
  197. // ExceptionRecord (a0) - Supplies a pointer to an exception record.
  198. //
  199. // ContextRecord (a1) - Supplies a pointer to a context record.
  200. //
  201. // FirstChance (a2) - Supplies a boolean value that determines whether
  202. // this is the first (TRUE) or second (FALSE) chance for dispatching
  203. // the exception.
  204. //
  205. // N.B. Register t0 is assumed to contain the address of a trap frame.
  206. //
  207. // Return Value:
  208. //
  209. // Normally there is no return from this routine. However, if the specified
  210. // context record or exception record is misaligned or is not accessible,
  211. // then the appropriate status code is returned.
  212. //
  213. //--
  214. NESTED_ENTRY(NtRaiseException)
  215. NESTED_SETUP(3,3,5,0)
  216. .fframe ExceptionFrameLength
  217. add sp = -ExceptionFrameLength, sp
  218. ;;
  219. PROLOGUE_END
  220. //
  221. // Pop this trap frame off the thread list.
  222. //
  223. add t2 = TrTrapFrame, t0
  224. movl t1 = KiPcr + PcCurrentThread
  225. ;;
  226. ld8 t1 = [t1]; // Get current thread.
  227. ld8 t2 = [t2]; // Load previous trap frame
  228. ;;
  229. add t1 = ThTrapFrame, t1
  230. //
  231. // Save nonvolatile states.
  232. //
  233. add out0 = STACK_SCRATCH_AREA, sp
  234. mov loc2 = t0 // save pointer to trap frame
  235. ;;
  236. st8 [t1] = t2
  237. br.call.sptk brp = KiSaveExceptionFrame
  238. //
  239. // Call the raise exception kernel routine wich will marshall the argments
  240. // and then call the exception dispatcher.
  241. //
  242. add out2 = STACK_SCRATCH_AREA, sp // -> exception frame
  243. mov out1 = a1
  244. mov out0 = a0
  245. add out4 = zero, a2
  246. mov out3 = t0
  247. br.call.sptk.many brp = KiRaiseException
  248. //
  249. // If the raise exception routine returns success, then exit via the exception
  250. // exit code. Otherwise, return to the system service dispatcher.
  251. //
  252. // N.B. The exception exit code will restore the exception frame & trap frame
  253. // and then rfi to user code.
  254. //
  255. // Set up for branch to KiExceptionExit
  256. //
  257. // s0 = trap frame
  258. // s1 = exception frame
  259. //
  260. pUstk = ps3
  261. pKstk = ps4
  262. cmp4.ne p0, pt1 = zero, v0 // if ne, dispatch failed.
  263. ;;
  264. //
  265. // Interrupts must be disabled before calling KiExceptionExit
  266. // because the unwind code cannot unwind from that point.
  267. //
  268. (pt1) FAST_DISABLE_INTERRUPTS
  269. (pt1) mov s0 = loc2 // copy trap frame pointer
  270. (pt1) add s1 = STACK_SCRATCH_AREA, sp
  271. (pt1) cmp.eq pUstk, pKstk = zero, zero
  272. (pt1) br.cond.sptk.many KiExceptionExit
  273. .restore
  274. add sp = ExceptionFrameLength, sp
  275. NESTED_RETURN
  276. NESTED_EXIT(NtRaiseException)
  277. //++
  278. //
  279. // VOID
  280. // KeFillLargeEntryTb (
  281. // IN HARDWARE_PTE Pte[],
  282. // IN PVOID Virtual,
  283. // IN ULONG PageSize
  284. // )
  285. //
  286. // Routine Description:
  287. //
  288. // This function fills a large translation buffer entry.
  289. //
  290. // N.B. It is assumed that the large entry is not in the TB and therefore
  291. // the TB is not probed.
  292. //
  293. // Arguments:
  294. //
  295. // Pte (a0) - Supplies a pointer to the page table entries that are to be
  296. // written into the TB.
  297. //
  298. // Virtual (a1) - Supplies the virtual address of the entry that is to
  299. // be filled in the translation buffer.
  300. //
  301. // PageSize (a2) - Supplies the size of the large page table entry.
  302. //
  303. // Return Value:
  304. //
  305. // None.
  306. //
  307. //--
  308. LEAF_ENTRY(KeFillLargeEntryTb)
  309. rPte = t0
  310. rScnd = t1
  311. ridtr = t2
  312. rid = t3
  313. rDtr = t4
  314. rTb = t6
  315. rTbPFN = t7
  316. rpAttr = t8
  317. rAttrOffset = t9
  318. shr.u rScnd = a2, 6 // mask off page size fields
  319. ;;
  320. shl rScnd = rScnd, 6 //
  321. ;;
  322. and rScnd = a1, rScnd // examine the virtual address bit
  323. ;;
  324. cmp.eq pt0, pt1 = r0, rScnd
  325. shl ridtr = a2, PS_SHIFT
  326. mov rDtr = DTR_VIDEO_INDEX
  327. ;;
  328. rsm 1 << PSR_I // turn off interrupts
  329. (pt0) add a0 = (1 << PTE_SHIFT), a0
  330. ;;
  331. ld8 rPte = [a0] // load PTE
  332. rsm 1 << PSR_IC // interrupt is off, now reset PSR.ic
  333. ;;
  334. srlz.d // serialize
  335. mov cr.itir = ridtr // idtr for insertion
  336. mov cr.ifa = a1 // ifa for insertion
  337. ;;
  338. itr.d dtr[rDtr] = rPte
  339. ssm 1 << PSR_IC // set PSR.ic bit again
  340. ;;
  341. srlz.i // I serialize
  342. ssm 1 << PSR_I
  343. LEAF_RETURN
  344. LEAF_EXIT(KeFillLargeEntryTb) // return
  345. //++
  346. //
  347. // VOID
  348. // KeFillFixedEntryTb (
  349. // IN HARDWARE_PTE Pte[],
  350. // IN PVOID Virtual,
  351. // IN ULONG PageSize,
  352. // IN ULONG Index
  353. // )
  354. //
  355. // Routine Description:
  356. //
  357. // This function fills a fixed translation buffer entry.
  358. //
  359. // Arguments:
  360. //
  361. // Pte (a0) - Supplies a pointer to the page table entries that are to be
  362. // written into the TB.
  363. //
  364. // Virtual (a1) - Supplies the virtual address of the entry that is to
  365. // be filled in the translation buffer.
  366. //
  367. // Index (a2) - Supplies the index where the TB entry is to be written.
  368. //
  369. // Return Value:
  370. //
  371. // None.
  372. //
  373. // Comments:
  374. //
  375. //
  376. //
  377. //--
  378. LEAF_ENTRY(KeFillFixedEntryTb)
  379. rPte = t0
  380. rScnd = t1
  381. ridtr = t2
  382. rid = t3
  383. rIndex = t4
  384. rTb = t6
  385. rTbPFN = t7
  386. rpAttr = t8
  387. rAttrOffset = t9
  388. rsm 1 << PSR_I // reset PSR.i
  389. ld8 rPte = [a0] // load PTE
  390. shl ridtr = a2, PS_SHIFT
  391. ;;
  392. rsm 1 << PSR_IC // interrupt is off, now reset PSR.ic
  393. tbit.z pt0, pt1 = a3, 31 // check the sign bit
  394. // if 1 ITR, otherwise DTR
  395. ;;
  396. srlz.d // serialize
  397. and rIndex = 0xf, a3
  398. ;;
  399. mov cr.itir = ridtr // idtr for insertion
  400. mov cr.ifa = a1 // ifa for insertion
  401. ;;
  402. (pt0) itr.d dtr[rIndex] = rPte // insert into DTR
  403. (pt1) itr.i itr[rIndex] = rPte // insert into ITR
  404. ssm 1 << PSR_IC // set PSR.ic bit again
  405. ;;
  406. srlz.i // I serialize
  407. #if DBG
  408. mov t10 = PbProcessorState+KpsSpecialRegisters+KsTrD0
  409. movl t13 = KiPcr + PcPrcb
  410. ;;
  411. ld8 t13 = [t13]
  412. mov t14 = PbProcessorState+KpsSpecialRegisters+KsTrI0
  413. ;;
  414. add t10 = t10, t13
  415. add t14 = t14, t13
  416. ;;
  417. (pt0) shladd t15 = rIndex, 3, t10
  418. (pt1) shladd t15 = rIndex, 3, t14
  419. ;;
  420. (pt0) st8 [t15] = rPte
  421. (pt1) st8 [t15] = rPte
  422. ;;
  423. #endif
  424. ssm 1 << PSR_I
  425. LEAF_RETURN
  426. LEAF_EXIT(KeFillFixedEntryTb)
  427. //++
  428. //
  429. // VOID
  430. // KeFillFixedLargeEntryTb (
  431. // IN HARDWARE_PTE Pte[],
  432. // IN PVOID Virtual,
  433. // IN ULONG PageSize,
  434. // IN ULONG Index
  435. // )
  436. //
  437. // Routine Description:
  438. //
  439. // This function fills a fixed translation buffer entry with a large page
  440. // size.
  441. //
  442. // Arguments:
  443. //
  444. // Pte (a0) - Supplies a pointer to the page table entries that are to be
  445. // written into the TB.
  446. //
  447. // Virtual (a1) - Supplies the virtual address of the entry that is to
  448. // be filled in the translation buffer.
  449. //
  450. // PageSize (a2) - Supplies the size of the large page table entry.
  451. //
  452. // Index (a3) - Supplies the index where the TB entry is to be written.
  453. //
  454. // Return Value:
  455. //
  456. // None.
  457. //
  458. // Comments:
  459. //
  460. // Yet to be implemented.
  461. //
  462. //--
  463. LEAF_ENTRY(KeFillFixedLargeEntryTb)
  464. rPte = t0
  465. rScnd = t1
  466. ridtr = t2
  467. rid = t3
  468. rIndex = t4
  469. rTb = t6
  470. rTbPFN = t7
  471. rpAttr = t8
  472. rAttrOffset = t9
  473. rsm 1 << PSR_I // reset PSR.i
  474. ld8 rPte = [a0] // load PTE
  475. shl ridtr = a2, PS_SHIFT
  476. ;;
  477. rsm 1 << PSR_IC // interrupt is off, now reset PSR.ic
  478. and rIndex = 0xf, a3 // set the DTR index
  479. tbit.z pt0, pt1 = a3, 31 // check the sign bit
  480. ;;
  481. srlz.d // serialize
  482. mov cr.itir = ridtr // idtr for insertion
  483. mov cr.ifa = a1 // ifa for insertion
  484. ;;
  485. (pt0) itr.d dtr[rIndex] = rPte // insert into DTR
  486. (pt1) itr.i itr[rIndex] = rPte // insert into ITR
  487. ssm 1 << PSR_IC // set PSR.ic bit again
  488. ;;
  489. srlz.i // I serialize
  490. ssm 1 << PSR_I
  491. LEAF_RETURN
  492. LEAF_EXIT(KeFillFixedLargeEntryTb) // return
  493. //++
  494. //
  495. // VOID
  496. // KeFillInstEntryTb (
  497. // IN HARDWARE_PTE Pte[],
  498. // IN PVOID Virtual,
  499. // )
  500. //
  501. // Routine Description:
  502. //
  503. // This function fills a large translation buffer entry.
  504. //
  505. // N.B. It is assumed that the large entry is not in the TB and therefore
  506. // the TB is not probed.
  507. //
  508. // Arguments:
  509. //
  510. // Pte (a0) - Supplies a page table entry that is to be
  511. // written into the Inst TB.
  512. //
  513. // Virtual (a1) - Supplies the virtual address of the entry that is to
  514. // be filled in the translation buffer.
  515. //
  516. // Return Value:
  517. //
  518. // None.
  519. //
  520. //--
  521. LEAF_ENTRY(KeFillInstEntryTb)
  522. riitr = t2
  523. rid = t3
  524. rsm 1 << PSR_I // reset PSR.i
  525. ;;
  526. rsm 1 << PSR_IC // interrupt is off, now reset PSR.ic
  527. mov riitr = PAGE_SIZE << PS_LEN
  528. ;;
  529. srlz.d // serialize
  530. mov cr.ifa = a1 // set va to install
  531. mov cr.itir = riitr // iitr for insertion
  532. ;;
  533. itc.i a0
  534. ;;
  535. ssm 1 << PSR_IC // set PSR.ic bit again
  536. ;;
  537. srlz.i // I serialize
  538. ssm 1 << PSR_I
  539. LEAF_RETURN
  540. LEAF_EXIT(KeFillInstEntryTb) // return
  541. //++
  542. //
  543. // VOID
  544. // KeBreakinBreakpoint
  545. // VOID
  546. // )
  547. //
  548. // Routine Description:
  549. //
  550. // This function causes a BREAKIN breakpoint.
  551. //
  552. // Arguments:
  553. //
  554. // None.
  555. //
  556. // Return Value:
  557. //
  558. // None.
  559. //
  560. //--
  561. LEAF_ENTRY(KeBreakinBreakpoint)
  562. //
  563. // Flush the RSE or the kernel debugger is unable to do a stack unwind
  564. //
  565. flushrs
  566. ;;
  567. break.i BREAKPOINT_BREAKIN
  568. LEAF_RETURN
  569. LEAF_EXIT(KeBreakinBreakpoint)
  570. #ifdef WX86
  571. //++
  572. //
  573. // VOID
  574. // KiIA32RegistersInit
  575. // VOID
  576. // )
  577. //
  578. // Routine Description:
  579. //
  580. // This function to Initialize per processor IA32 related registers
  581. // These registers do not saved/restored on context switch time
  582. //
  583. // Arguments:
  584. //
  585. // None.
  586. //
  587. // Return Value:
  588. //
  589. // None.
  590. //
  591. //--
  592. LEAF_ENTRY(KiIA32RegistersInit)
  593. mov t0 = TeGdtDescriptor
  594. mov iA32iobase = 0
  595. ;;
  596. mov iA32index = t0
  597. LEAF_RETURN
  598. LEAF_EXIT(KiIA32RegistersInit)
  599. #endif // WX86
  600. //++
  601. //
  602. // PKTHREAD
  603. // KeGetCurrentThread (VOID)
  604. //
  605. // Routine Description:
  606. //
  607. // Arguments:
  608. //
  609. // None.
  610. //
  611. // Return Value:
  612. //
  613. // Returns a pointer to the executing thread object.
  614. //
  615. //--
  616. LEAF_ENTRY(KeGetCurrentThread)
  617. movl v0 = KiPcr + PcCurrentThread // -> current thread
  618. ;;
  619. ld8 v0 = [v0]
  620. br.ret.sptk brp
  621. LEAF_EXIT(KeGetCurrentThread)
  622. //++
  623. //
  624. // BOOLEAN
  625. // KeIsExecutingDpc (VOID)
  626. //
  627. // Routine Description:
  628. //
  629. // Arguments:
  630. //
  631. // None.
  632. //
  633. // Return Value:
  634. //
  635. // Return a value which indicates if we are currently in a DPC.
  636. //
  637. //--
  638. LEAF_ENTRY(KeIsExecutingDpc)
  639. rsm 1 << PSR_I // disable interrupt
  640. movl v0 = KiPcr + PcPrcb
  641. ;;
  642. ld8 v0 = [v0]
  643. ;;
  644. add v0 = PbDpcRoutineActive, v0
  645. ;;
  646. ld4 v0 = [v0]
  647. ssm 1 << PSR_I // enable interrupt
  648. br.ret.sptk brp
  649. LEAF_EXIT(KeIsExecutingDpc)
  650. //++
  651. //
  652. // Routine Description:
  653. //
  654. // This routine saves the thread's current non-volatile NPX state,
  655. // and sets a new initial floating point state for the caller.
  656. //
  657. // This is intended for use by kernel-mode code that needs to use
  658. // the floating point registers. Must be paired with
  659. // KeRestoreFloatingPointState
  660. //
  661. // Arguments:
  662. //
  663. // a0 - Supplies pointer to KFLOATING_SAVE structure
  664. //
  665. // Return Value:
  666. //
  667. // None.
  668. //
  669. //--
  670. LEAF_ENTRY(KeSaveFloatingPointState)
  671. mov v0 = zero
  672. LEAF_RETURN
  673. LEAF_EXIT(KeSaveFloatingPointState)
  674. //++
  675. //
  676. // Routine Description:
  677. //
  678. // This routine restores the thread's current non-volatile NPX state,
  679. // to the passed in state.
  680. //
  681. // This is intended for use by kernel-mode code that needs to use
  682. // the floating point registers. Must be paired with
  683. // KeSaveFloatingPointState
  684. //
  685. // Arguments:
  686. //
  687. // a0 - Supplies pointer to KFLOATING_SAVE structure
  688. //
  689. // Return Value:
  690. //
  691. // None.
  692. //
  693. //--
  694. LEAF_ENTRY(KeRestoreFloatingPointState)
  695. mov v0 = zero
  696. LEAF_RETURN
  697. LEAF_EXIT(KeRestoreFloatingPointState)
  698. //++
  699. //
  700. // Routine Description:
  701. //
  702. // This routine flush all the dirty registers to the backing store
  703. // and invalidate them.
  704. //
  705. // Arguments:
  706. //
  707. // None.
  708. //
  709. // Return Value:
  710. //
  711. // None.
  712. //
  713. //--
  714. LEAF_ENTRY(KiFlushRse)
  715. flushrs
  716. mov t1 = ar.rsc
  717. mov t0 = RSC_KERNEL_DISABLED
  718. ;;
  719. mov ar.rsc = t0
  720. ;;
  721. loadrs
  722. ;;
  723. mov ar.rsc = t1
  724. ;;
  725. br.ret.sptk brp
  726. LEAF_EXIT(KiFlushRse)
  727. #if 0
  728. //++
  729. //
  730. // Routine Description:
  731. //
  732. // This routine invalidate all the physical stacked registers.
  733. //
  734. // Arguments:
  735. //
  736. // None.
  737. //
  738. // Return Value:
  739. //
  740. // None.
  741. //
  742. //--
  743. LEAF_ENTRY(KiInvalidateStackedRegisters)
  744. mov t1 = ar.rsc
  745. mov t0 = RSC_KERNEL_DISABLED
  746. ;;
  747. mov ar.rsc = t0
  748. ;;
  749. loadrs
  750. ;;
  751. mov ar.rsc = t1
  752. ;;
  753. br.ret.sptk brp
  754. LEAF_EXIT(KiInvalidateStackedRegisters)
  755. #endif // 0
  756. //++
  757. //
  758. // VOID
  759. // KeSetLowPsrBit (
  760. // UCHAR BitPosition,
  761. // BOOLEAN Value
  762. // )
  763. //
  764. // Routine Description:
  765. //
  766. // This routine set one of the low psr bits to the specified value.
  767. //
  768. // Arguments:
  769. //
  770. // a0 - bit position
  771. // a1 - 1 or 0
  772. //
  773. // Return Value:
  774. //
  775. // None.
  776. //
  777. //--
  778. LEAF_ENTRY(KeSetLowPsrBit)
  779. mov t1 = psr
  780. mov t2 = 1
  781. cmp.ne pt1, pt0 = r0, a1
  782. ;;
  783. shl t2 = t2, a0
  784. ;;
  785. (pt1) or t3 = t1, t2
  786. (pt0) andcm t3 = t1, t2
  787. ;;
  788. mov psr.l = t3
  789. ;;
  790. srlz.i
  791. br.ret.sptk brp
  792. LEAF_EXIT(KeSetLowPsrBit)
  793. //++
  794. //
  795. // PVOID
  796. // KiGetPhysicalAddress(
  797. // PVOID Virtual
  798. // )
  799. //
  800. // Routine Description:
  801. //
  802. // This routine translates to physical address uing TPA instruction.
  803. //
  804. // Arguments:
  805. //
  806. // a0 - virtual address to be translated to physical address.
  807. //
  808. // Return Value:
  809. //
  810. // physical address
  811. //
  812. //--
  813. LEAF_ENTRY(KiGetPhysicalAddress)
  814. tpa r8 = a0
  815. LEAF_RETURN
  816. LEAF_EXIT(KiGetPhysicalAddress)
  817. //++
  818. //
  819. // VOID
  820. // KiSetRegionRegister(
  821. // PVOID Region,
  822. // ULONGLONG Contents
  823. // )
  824. //
  825. // Routine Description:
  826. //
  827. // This routine sets the value of a region register.
  828. //
  829. // Arguments:
  830. //
  831. // a0 - Supplies the region register #
  832. //
  833. // a1 - Supplies the value to be stored in the specified region register
  834. //
  835. // Return Value:
  836. //
  837. // None.
  838. //
  839. //--
  840. LEAF_ENTRY(KiSetRegionRegister)
  841. mov rr[a0] = a1
  842. ;;
  843. srlz.i
  844. LEAF_RETURN
  845. LEAF_EXIT(KiSetRegionId)
  846. LEAF_ENTRY(KiSaveProcessorControlState)
  847. //
  848. // save region registers
  849. //
  850. add t2 = KpsSpecialRegisters+KsRr0, a0
  851. dep.z t0 = 0, RR_INDEX, RR_INDEX_LEN
  852. ;;
  853. mov t1 = rr[t0]
  854. dep.z t3 = 1, RR_INDEX, RR_INDEX_LEN
  855. ;;
  856. mov t4 = rr[t3]
  857. st8 [t2] = t1, KsRr1-KsRr0
  858. dep.z t0 = 2, RR_INDEX, RR_INDEX_LEN
  859. ;;
  860. mov t1 = rr[t0]
  861. st8 [t2] = t4, KsRr2-KsRr1
  862. dep.z t3 = 3, RR_INDEX, RR_INDEX_LEN
  863. ;;
  864. mov t4 = rr[t3]
  865. st8 [t2] = t1, KsRr3-KsRr2
  866. dep.z t0 = 4, RR_INDEX, RR_INDEX_LEN
  867. ;;
  868. mov t1 = rr[t0]
  869. st8 [t2] = t4, KsRr4-KsRr3
  870. dep.z t3 = 5, RR_INDEX, RR_INDEX_LEN
  871. ;;
  872. mov t4 = rr[t3]
  873. st8 [t2] = t1, KsRr5-KsRr4
  874. dep.z t0 = 6, RR_INDEX, RR_INDEX_LEN
  875. ;;
  876. mov t1 = rr[t0]
  877. st8 [t2] = t4, KsRr6-KsRr5
  878. dep.z t3 = 7, RR_INDEX, RR_INDEX_LEN
  879. ;;
  880. mov t4 = rr[t3]
  881. st8 [t2] = t1, KsRr7-KsRr6
  882. ;;
  883. st8 [t2] = t4
  884. //
  885. // save ITC, ITM, IVA, PTA and TPR
  886. //
  887. mov t0 = ar.itc
  888. mov t1 = cr.itm
  889. add t3 = KpsSpecialRegisters+KsApITC, a0
  890. add t4 = KpsSpecialRegisters+KsApITM, a0
  891. ;;
  892. mov t5 = cr.iva
  893. mov t6 = cr.pta
  894. st8 [t3] = t0, KsApIVA-KsApITC
  895. st8 [t4] = t1, KsApPTA-KsApITM
  896. ;;
  897. mov t0 = cr.tpr
  898. mov t1 = ar.k0
  899. st8 [t3] = t5, KsSaTPR-KsApIVA
  900. st8 [t4] = t6, KsApKR0-KsApPTA
  901. ;;
  902. mov t5 = ar.k1
  903. mov t6 = ar.k2
  904. st8 [t3] = t0, KsApKR1-KsSaTPR
  905. st8 [t4] = t1, KsApKR2-KsApKR0
  906. ;;
  907. mov t0 = ar.k3
  908. mov t1 = ar.k4
  909. st8 [t3] = t5, KsApKR3-KsApKR1
  910. st8 [t4] = t6, KsApKR4-KsApKR2
  911. ;;
  912. mov t5 = ar.k5
  913. mov t6 = ar.k6
  914. st8 [t3] = t0, KsApKR5-KsApKR3
  915. st8 [t4] = t1, KsApKR6-KsApKR4
  916. ;;
  917. mov t0 = ar.k7
  918. mov t1 = cr.lid
  919. st8 [t3] = t5, KsApKR7-KsApKR5
  920. st8 [t4] = t6, KsSaLID-KsApKR6
  921. ;;
  922. mov t5 = cr.irr0
  923. mov t6 = cr.irr1
  924. st8 [t3] = t0, KsSaIRR0-KsApKR7
  925. st8 [t4] = t1, KsSaIRR1-KsSaLID
  926. ;;
  927. mov t0 = cr.irr2
  928. mov t1 = cr.irr3
  929. st8 [t3] = t5, KsSaIRR2-KsSaIRR0
  930. st8 [t4] = t6, KsSaIRR3-KsSaIRR1
  931. ;;
  932. mov t5 = cr.itv
  933. mov t6 = cr.pmv
  934. st8 [t3] = t0, KsSaITV-KsSaIRR2
  935. st8 [t4] = t1, KsSaPMV-KsSaIRR3
  936. ;;
  937. mov t0 = cr.cmcv
  938. mov t1 = cr.lrr0
  939. st8 [t3] = t5, KsSaCMCV-KsSaITV
  940. st8 [t4] = t6, KsSaLRR0-KsSaPMV
  941. ;;
  942. mov t5 = cr.lrr1
  943. mov t6 = cr.gpta
  944. st8 [t3] = t0, KsSaLRR1-KsSaCMCV
  945. st8 [t4] = t1, KsApGPTA-KsSaLRR0
  946. mov t7 = 0
  947. mov t8 = 1
  948. ;;
  949. mov t0 = cpuid[t7]
  950. mov t1 = cpuid[t8]
  951. st8 [t3] = t5
  952. st8 [t4] = t6
  953. mov t9 = 2
  954. mov t10 = 3
  955. add t3 = KpsSpecialRegisters+KsApCPUID0, a0
  956. add t4 = KpsSpecialRegisters+KsApCPUID1, a0
  957. ;;
  958. mov t5 = cpuid[t9]
  959. mov t6 = cpuid[t10]
  960. st8 [t3] = t0, KsApCPUID2-KsApCPUID0
  961. st8 [t4] = t1, KsApCPUID3-KsApCPUID1
  962. mov t7 = 4
  963. mov t8 = 652
  964. ;;
  965. mov t0 = cpuid[t7]
  966. st8 [t3] = t5, KsApCPUID4-KsApCPUID2
  967. st8 [t4] = t6
  968. ;;
  969. st8 [t3] = t0
  970. LEAF_RETURN
  971. LEAF_EXIT(KiSaveProcessorControlState)
  972. NESTED_ENTRY(KiRestoreProcessorControlState)
  973. NESTED_SETUP(0,2,0,0)
  974. ;;
  975. br.call.spnt brp = KiLoadKernelDebugRegisters
  976. ;;
  977. NESTED_RETURN
  978. NESTED_EXIT(KiRestoreProcessorControlState)
  979. PublicFunction(KiSaveExceptionFrame)
  980. PublicFunction(KiRestoreExceptionFrame)
  981. PublicFunction(KiIpiServiceRoutine)
  982. NESTED_ENTRY(KeIpiInterrupt)
  983. NESTED_SETUP(1, 2, 2, 0)
  984. .fframe ExceptionFrameLength
  985. add sp = -ExceptionFrameLength, sp
  986. ;;
  987. PROLOGUE_END
  988. add out0 = STACK_SCRATCH_AREA, sp // -> exception frame
  989. br.call.sptk brp = KiSaveExceptionFrame
  990. ;;
  991. add out1 = STACK_SCRATCH_AREA, sp // -> exception frame
  992. mov out0 = a0 // -> trap frame
  993. br.call.sptk brp = KiIpiServiceRoutine
  994. ;;
  995. add out0 = STACK_SCRATCH_AREA, sp // -> exception frame
  996. br.call.sptk brp = KiRestoreExceptionFrame
  997. ;;
  998. add sp = ExceptionFrameLength, sp
  999. NESTED_RETURN
  1000. NESTED_EXIT(KeIpiInterrupt)
  1001. LEAF_ENTRY(KiReadMsr)
  1002. mov v0 = msr[a0]
  1003. LEAF_RETURN
  1004. LEAF_EXIT(KiReadMsr)
  1005. LEAF_ENTRY(KiWriteMsr)
  1006. mov msr[a0] = a1
  1007. LEAF_RETURN
  1008. LEAF_EXIT(KiWriteMsr)