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.

632 lines
18 KiB

  1. // TITLE("Register Save and Restore")
  2. //++
  3. //
  4. // Copyright (c) 1992 Digital Equipment Corporation
  5. //
  6. // Module Name:
  7. //
  8. // regsav.s
  9. //
  10. // Abstract:
  11. //
  12. // Implements save/restore general purpose processor
  13. // registers during exception handling
  14. //
  15. // Author:
  16. //
  17. // Joe Notarangelo 06-May-1992
  18. //
  19. // Environment:
  20. //
  21. // Kernel mode only.
  22. //
  23. // Revision History:
  24. //
  25. //--
  26. #include "ksalpha.h"
  27. SBTTL("Generate Trap Frame")
  28. //++
  29. //
  30. // Routine Description:
  31. //
  32. // Save volatile register state (integer/float) in
  33. // a trap frame.
  34. //
  35. // Note: control registers, ra, sp, fp, gp have already
  36. // been saved, argument registers a0-a3 have also been saved.
  37. //
  38. // Arguments:
  39. //
  40. // fp - Supplies a pointer to the trap frame.
  41. //
  42. // Return Value:
  43. //
  44. // None.
  45. //
  46. //--
  47. LEAF_ENTRY(KiGenerateTrapFrame)
  48. stq v0, TrIntV0(fp) // save integer register v0
  49. stq t0, TrIntT0(fp) // save integer registers t0 - t7
  50. stq t1, TrIntT1(fp) //
  51. stq t2, TrIntT2(fp) //
  52. stq t3, TrIntT3(fp) //
  53. stq t4, TrIntT4(fp) //
  54. stq t5, TrIntT5(fp) //
  55. stq t6, TrIntT6(fp) //
  56. stq t7, TrIntT7(fp) //
  57. stq a4, TrIntA4(fp) // save integer registers a4 - a5
  58. stq a5, TrIntA5(fp) //
  59. stq t8, TrIntT8(fp) // save integer registers t8 - t12
  60. stq t9, TrIntT9(fp) //
  61. stq t10, TrIntT10(fp) //
  62. stq t11, TrIntT11(fp) //
  63. stq t12, TrIntT12(fp) //
  64. .set noat
  65. stq AT, TrIntAt(fp) // save integer register AT
  66. .set at
  67. br zero, KiSaveVolatileFloatState // save volatile float state
  68. .end KiGenerateTrapFrame
  69. SBTTL("Restore Trap Frame")
  70. //++
  71. //
  72. // Routine Description:
  73. //
  74. // Restore volatile register state (integer/float) from
  75. // a trap frame
  76. //
  77. // Note: control registers, ra, sp, fp, gp will be
  78. // restored by the PALcode, as will argument registers a0-a3.
  79. //
  80. // Arguments:
  81. //
  82. // fp - Supplies a pointer to trap frame.
  83. //
  84. // Return Value:
  85. //
  86. // None.
  87. //
  88. //--
  89. LEAF_ENTRY(KiRestoreTrapFrame)
  90. ldq v0, TrIntV0(fp) // restore integer register v0
  91. ldq t0, TrIntT0(fp) // restore integer registers t0 - t7
  92. ldq t1, TrIntT1(fp) //
  93. ldq t2, TrIntT2(fp) //
  94. ldq t3, TrIntT3(fp) //
  95. ldq t4, TrIntT4(fp) //
  96. ldq t5, TrIntT5(fp) //
  97. ldq t6, TrIntT6(fp) //
  98. ldq t7, TrIntT7(fp) //
  99. ldq a4, TrIntA4(fp) // restore integer registers a4 - a5
  100. ldq a5, TrIntA5(fp) //
  101. ldq t8, TrIntT8(fp) // restore integer registers t8 - t12
  102. ldq t9, TrIntT9(fp) //
  103. ldq t10, TrIntT10(fp) //
  104. ldq t11, TrIntT11(fp) //
  105. ldq t12, TrIntT12(fp) //
  106. .set noat
  107. ldq AT, TrIntAt(fp) // restore integer register AT
  108. .set at
  109. //
  110. // Restore the volatile floating register state
  111. //
  112. br zero, KiRestoreVolatileFloatState //
  113. .end KiRestoreTrapFrame
  114. SBTTL("Save Volatile Floating Registers")
  115. //++
  116. //
  117. // Routine Description:
  118. //
  119. // Save volatile floating registers in a trap frame.
  120. //
  121. // Arguments:
  122. //
  123. // fp - Supplies a pointer to the trap frame.
  124. //
  125. // Return Value:
  126. //
  127. // None.
  128. //
  129. //--
  130. LEAF_ENTRY(KiSaveVolatileFloatState)
  131. //
  132. // asaxp is broken, it does not know that mf_fpcr f0
  133. // destroys f0.
  134. //
  135. .set noreorder
  136. stt f0, TrFltF0(fp) // save floating register f0
  137. mf_fpcr f0 // save fp control register
  138. .set reorder
  139. stt f0, TrFpcr(fp) //
  140. stt f1, TrFltF1(fp) // save floating register f1
  141. stt f10, TrFltF10(fp) // save floating registers f10 - f30
  142. stt f11, TrFltF11(fp) //
  143. stt f12, TrFltF12(fp) //
  144. stt f13, TrFltF13(fp) //
  145. stt f14, TrFltF14(fp) //
  146. stt f15, TrFltF15(fp) //
  147. stt f16, TrFltF16(fp) //
  148. stt f17, TrFltF17(fp) //
  149. stt f18, TrFltF18(fp) //
  150. stt f19, TrFltF19(fp) //
  151. stt f20, TrFltF20(fp) //
  152. stt f21, TrFltF21(fp) //
  153. stt f22, TrFltF22(fp) //
  154. stt f23, TrFltF23(fp) //
  155. stt f24, TrFltF24(fp) //
  156. stt f25, TrFltF25(fp) //
  157. stt f26, TrFltF26(fp) //
  158. stt f27, TrFltF27(fp) //
  159. stt f28, TrFltF28(fp) //
  160. stt f29, TrFltF29(fp) //
  161. stt f30, TrFltF30(fp) //
  162. ret zero, (ra) // return
  163. .end KiSaveVolatileFloatState
  164. SBTTL("Restore Volatile Floating State")
  165. //++
  166. //
  167. // Routine Description:
  168. //
  169. // Restore volatile floating registers from a trap frame.
  170. //
  171. //
  172. // Arguments:
  173. //
  174. // fp - pointer to trap frame
  175. //
  176. // Return Value:
  177. //
  178. // None.
  179. //
  180. //--
  181. LEAF_ENTRY(KiRestoreVolatileFloatState)
  182. ldt f0, TrFpcr(fp) // restore fp control register
  183. mt_fpcr f0 //
  184. ldt f0, TrFltF0(fp) // restore floating registers f0 - f1
  185. ldt f1, TrFltF1(fp) //
  186. ldt f10, TrFltF10(fp) // restore floating registers f10 - f30
  187. ldt f11, TrFltF11(fp) //
  188. ldt f12, TrFltF12(fp) //
  189. ldt f13, TrFltF13(fp) //
  190. ldt f14, TrFltF14(fp) //
  191. ldt f15, TrFltF15(fp) //
  192. ldt f16, TrFltF16(fp) //
  193. ldt f17, TrFltF17(fp) //
  194. ldt f18, TrFltF18(fp) //
  195. ldt f19, TrFltF19(fp) //
  196. ldt f20, TrFltF20(fp) //
  197. ldt f21, TrFltF21(fp) //
  198. ldt f22, TrFltF22(fp) //
  199. ldt f23, TrFltF23(fp) //
  200. ldt f24, TrFltF24(fp) //
  201. ldt f25, TrFltF25(fp) //
  202. ldt f26, TrFltF26(fp) //
  203. ldt f27, TrFltF27(fp) //
  204. ldt f28, TrFltF28(fp) //
  205. ldt f29, TrFltF29(fp) //
  206. ldt f30, TrFltF30(fp) //
  207. ret zero, (ra) // return
  208. .end KiRestoreVolatileFloatState
  209. SBTTL("Save Non-Volatile Floating State")
  210. //++
  211. //
  212. // Routine Description:
  213. //
  214. // Save nonvolatile floating registers in
  215. // an exception frame
  216. //
  217. //
  218. // Arguments:
  219. //
  220. // sp - pointer to exception frame
  221. //
  222. // Return Value:
  223. //
  224. // None.
  225. //
  226. //--
  227. LEAF_ENTRY(KiSaveNonVolatileFloatState)
  228. stt f2, ExFltF2(sp) // save floating registers f2 - f9
  229. stt f3, ExFltF3(sp) //
  230. stt f4, ExFltF4(sp) //
  231. stt f5, ExFltF5(sp) //
  232. stt f6, ExFltF6(sp) //
  233. stt f7, ExFltF7(sp) //
  234. stt f8, ExFltF8(sp) //
  235. stt f9, ExFltF9(sp) //
  236. ret zero, (ra) // return
  237. .end KiSaveNonVolatileFloatState
  238. SBTTL("Restore Non-Volatile Floating State")
  239. //++
  240. //
  241. // Routine Description:
  242. //
  243. // Restore nonvolatile floating registers from an exception frame.
  244. //
  245. //
  246. // Arguments:
  247. //
  248. // sp - Supplies a pointer to an exception frame.
  249. //
  250. // Return Value:
  251. //
  252. // None.
  253. //
  254. //--
  255. LEAF_ENTRY(KiRestoreNonVolatileFloatState)
  256. ldt f2, ExFltF2(sp) // restore floating registers f2 - f9
  257. ldt f3, ExFltF3(sp) //
  258. ldt f4, ExFltF4(sp) //
  259. ldt f5, ExFltF5(sp) //
  260. ldt f6, ExFltF6(sp) //
  261. ldt f7, ExFltF7(sp) //
  262. ldt f8, ExFltF8(sp) //
  263. ldt f9, ExFltF9(sp) //
  264. ret zero, (ra) // return
  265. .end KiRestoreNonVolatileFloatState
  266. SBTTL("Save Volatile Integer State")
  267. //++
  268. //
  269. // Routine Description:
  270. //
  271. // Save volatile integer register state in a trap frame.
  272. //
  273. // Note: control registers, ra, sp, fp, gp have already been saved
  274. // as have argument registers a0-a3.
  275. //
  276. // Arguments:
  277. //
  278. // fp - Supplies a pointer to the trap frame.
  279. //
  280. // Return Value:
  281. //
  282. // None.
  283. //
  284. //--
  285. LEAF_ENTRY( KiSaveVolatileIntegerState)
  286. stq v0, TrIntV0(fp) // save integer register v0
  287. stq t0, TrIntT0(fp) // save integer registers t0 - t7
  288. stq t1, TrIntT1(fp) //
  289. stq t2, TrIntT2(fp) //
  290. stq t3, TrIntT3(fp) //
  291. stq t4, TrIntT4(fp) //
  292. stq t5, TrIntT5(fp) //
  293. stq t6, TrIntT6(fp) //
  294. stq t7, TrIntT7(fp) //
  295. stq a4, TrIntA4(fp) // save integer registers a4 - a5
  296. stq a5, TrIntA5(fp) //
  297. stq t8, TrIntT8(fp) // save integer registers t8 - t12
  298. stq t9, TrIntT9(fp) //
  299. stq t10, TrIntT10(fp) //
  300. stq t11, TrIntT11(fp) //
  301. stq t12, TrIntT12(fp) //
  302. .set noat
  303. stq AT, TrIntAt(fp) // save integer register AT
  304. .set at
  305. ret zero, (ra) // return
  306. .end KiSaveVolatileIntegerState
  307. SBTTL("Restore Volatile Integer State")
  308. //++
  309. //
  310. // Routine Description:
  311. //
  312. // Restore volatile integer register state from a trap frame.
  313. //
  314. // Note: control registers, ra, sp, fp, gp and argument registers
  315. // a0 - a3 will be restored by the PALcode.
  316. //
  317. // Arguments:
  318. //
  319. // fp - Supplies a pointer to the trap frame.
  320. //
  321. // Return Value:
  322. //
  323. // None.
  324. //
  325. //--
  326. LEAF_ENTRY(KiRestoreVolatileIntegerState)
  327. ldq v0, TrIntV0(fp) // restore integer register v0
  328. ldq t0, TrIntT0(fp) // restore integer registers t0 - t7
  329. ldq t1, TrIntT1(fp) //
  330. ldq t2, TrIntT2(fp) //
  331. ldq t3, TrIntT3(fp) //
  332. ldq t4, TrIntT4(fp) //
  333. ldq t5, TrIntT5(fp) //
  334. ldq t6, TrIntT6(fp) //
  335. ldq t7, TrIntT7(fp) //
  336. ldq a4, TrIntA4(fp) // restore integer registers a4 - a5
  337. ldq a5, TrIntA5(fp) //
  338. ldq t8, TrIntT8(fp) // restore integer registers t8 - t12
  339. ldq t9, TrIntT9(fp) //
  340. ldq t10, TrIntT10(fp) //
  341. ldq t11, TrIntT11(fp) //
  342. ldq t12, TrIntT12(fp) //
  343. .set noat
  344. ldq AT, TrIntAt(fp) // restore integer register AT
  345. .set at
  346. ret zero, (ra) // return
  347. .end KiRestoreVolatileIntegerState
  348. SBTTL("Save Floating Point State")
  349. //++
  350. //
  351. // Routine Description:
  352. //
  353. // This routine saves the thread's current non-volatile NPX state,
  354. // and sets a new initial floating point state for the caller.
  355. //
  356. // This is intended for use by kernel-mode code that needs to use
  357. // the floating point registers. Must be paired with
  358. // KeRestoreFloatingPointState
  359. //
  360. // N.B. Currently this saves only the hardware FPCR. Software
  361. // emulation is not supported. Floating point from within
  362. // a DPC is not supported.
  363. //
  364. // Arguments:
  365. //
  366. // a0 - Supplies pointer to KFLOATING_SAVE structure
  367. //
  368. // Return Value:
  369. //
  370. // None.
  371. //
  372. //--
  373. LEAF_ENTRY(KeSaveFloatingPointState)
  374. //
  375. // Generate default FPCR value
  376. //
  377. ldiq t0, 0x0800000000000000
  378. stq t0, KfsReserved1(a0)
  379. ldt f1, KfsReserved1(a0)
  380. //
  381. // asaxp is broken, it does not know that mf_fpcr f0
  382. // destroys f0.
  383. //
  384. .set noreorder
  385. mf_fpcr f0 // save fp control register
  386. .set reorder
  387. stt f0, KfsFpcr(a0) //
  388. //
  389. // Set default mode - ROUND_TO_NEAREST
  390. //
  391. mt_fpcr f1 //
  392. bis zero, zero, v0 // always return success
  393. ret zero, (ra) // return
  394. .end KeSaveFloatingPointState
  395. SBTTL("Restore Floating Point State")
  396. //++
  397. //
  398. // Routine Description:
  399. //
  400. // This routine restores the thread's current non-volatile NPX state,
  401. // to the passed in state.
  402. //
  403. // This is intended for use by kernel-mode code that needs to use
  404. // the floating point registers. Must be paired with
  405. // KeSaveFloatingPointState
  406. //
  407. // N.B. Currently this restores only the hardware FPCR. Software
  408. // emulation is not supported. Floating point from within
  409. // a DPC is not supported.
  410. //
  411. // Arguments:
  412. //
  413. // a0 - Supplies pointer to KFLOATING_SAVE structure
  414. //
  415. // Return Value:
  416. //
  417. // None.
  418. //
  419. //--
  420. LEAF_ENTRY(KeRestoreFloatingPointState)
  421. ldt f0, KfsFpcr(a0) // restore fp control register
  422. mt_fpcr f0 //
  423. bis zero, zero, v0 // always return success
  424. ret zero, (ra) // return
  425. .end KeRestoreFloatingPointState
  426. SBTTL("Save State For Hibernate")
  427. //++
  428. //
  429. // VOID
  430. // KeSaveStateForHibernate(
  431. // IN PKPROCESSOR_STATE ProcessorState
  432. // )
  433. // /*++
  434. //
  435. // Routine Description:
  436. //
  437. // Saves all processor-specific state that must be preserved
  438. // across an S4 state (hibernation).
  439. //
  440. // Arguments:
  441. //
  442. // ProcessorState - Supplies the KPROCESSOR_STATE where the
  443. // current CPU's state is to be saved.
  444. //
  445. // Return Value:
  446. //
  447. // None.
  448. //
  449. //--
  450. .struct 0
  451. KsRa: .space 8
  452. KsA0: .space 8
  453. SaveStateLength:
  454. NESTED_ENTRY(KeSaveStateForHibernate, SaveStateLength,zero)
  455. lda sp, -SaveStateLength(sp) // allocate stack frame
  456. stq ra, KsRa(sp) // save return address
  457. PROLOGUE_END
  458. stq a0, KsA0(sp)
  459. bsr ra, RtlCaptureContext
  460. ldq t1, KsA0(sp) // get copy of context pointer
  461. lda a1, CxIntA1(t1) // SleepData pointer will be restored to a1
  462. //
  463. // The processor context when calling cp_sleep is the one that will be
  464. // restored by the PAL code when doing the restore. A0 contains the
  465. // address at which execution will resume. We resume in this function so
  466. // that SP gets readjusted to the callers value. However, we must be
  467. // careful not to reference anything in our stack frame after a resume
  468. // as that data was not saved to disk.
  469. //
  470. lda a0, do_return // address at which restore continues execution
  471. ldq ra, KsRa(sp) // address to return to after continuing
  472. ldil v0, 0 // return value on wakeup
  473. call_pal cp_sleep // save PAL state
  474. //
  475. // v0 is now the PALmode (physical) address of the PALcode restore routine, i.e. where
  476. // to jump to in PALmode.
  477. //
  478. stq v0, CxIntA2(t1) // it will be in a2
  479. // Set the address to start up at when first entered (the swppal to enter PALmode).
  480. lda t2, reentry // address of startup code below
  481. stq t2, CxFir(t1) // store startup address in CONTEXT
  482. //
  483. // Set the address for swppal to transfer control to in PALmode. This must be in a0
  484. // when swppal is executed.
  485. //
  486. lda t3, gorestore // address of transfer to restore below
  487. sll t3, 33, t3 // clear high-order 33 bits to convert
  488. srl t3, 33, t3 // to PALmode physical address
  489. stq t3, CxIntA0(t1)
  490. //
  491. // Return.
  492. //
  493. ldq ra, KsRa(sp) // restore return address
  494. do_return:
  495. lda sp, SaveStateLength(sp) // deallocate stack frame
  496. ret zero, (ra) // return
  497. //
  498. // This is where the OS Loader transfers control back to NT. The CONTEXT was
  499. // set up to direct execution here with registers set as follows:
  500. //
  501. // a0 - PALmode address of code to be executed in PALmode (gorestore)
  502. // a1 - pointer to the SleepData structure (returned by sleep)
  503. // a2 - PALmode address of the restore routine (returned by sleep)
  504. //
  505. // All other registers are presently "don't care", but the code in OS Loader
  506. // that transfers control should restore the entire CONTEXT so that it remains
  507. // compatible even if this convention changes.
  508. reentry:
  509. #if defined(DBG_LEDS)
  510. // LED display: F1
  511. ldiq t0, 0xfffffc0000000000+0x87A0000180
  512. ldil t1, 0xF1
  513. stq t1, (t0)
  514. mb
  515. ldil t0, 166666666
  516. 1:
  517. subl t0, 1, t0
  518. bne t0, 1b
  519. #endif
  520. call_pal swppal // simply enter PALmode, transfer to
  521. // following code
  522. //
  523. // Control is transferred here in PALmode by swppal. a1 contains the pointer
  524. // to the SleepData structure, and a2 contains the PALmode address of the
  525. // restore routine.
  526. //
  527. gorestore:
  528. #if defined(DBG_LEDS)
  529. // LED display: F2
  530. ldiq t0, 0xfffffc0000000000+0x87A0000180
  531. ldil t1, 0xF2
  532. stq t1, (t0)
  533. mb
  534. ldil t0, 166666666
  535. 1:
  536. subl t0, 1, t0
  537. bne t0, 1b
  538. #endif
  539. bis a1, 0, a0 // restore needs SleepData pointer in a0
  540. jmp (a2) // jump to restore routine
  541. .end KeSaveStateForHibernate