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.

458 lines
12 KiB

  1. title "Sleep Context"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; ixslpctx.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements the code for saving processor
  13. ; context before putting the machine to sleep. It also
  14. ; contains the code for building a page that a processor
  15. ; in real mode can jump to in order to transition into
  16. ; p-mode and assume a thread context.
  17. ;
  18. ; Author:
  19. ;
  20. ; Jake Oshins (jakeo) March 13, 1998
  21. ;
  22. ; Environment:
  23. ;
  24. ; Kernel mode only.
  25. ;
  26. ; Revision History:
  27. ;
  28. ; Much of this code has been moved from halmps\i386\mpsproca.asm.
  29. ;
  30. ;--
  31. .386p
  32. .xlist
  33. include hal386.inc
  34. include callconv.inc ; calling convention macros
  35. include apic.inc
  36. include i386\ixslpctx.inc
  37. include mac386.inc
  38. .list
  39. extrn _HalpLowStub:DWORD
  40. extrn _KeSaveStateForHibernate:proc
  41. ifdef ACPI_HAL
  42. EXTRNP HalpAcpiFlushCache, 0,,FASTCALL
  43. endif
  44. PAGELK16 SEGMENT DWORD PUBLIC USE16 'CODE' ; start 16 bit code
  45. ;++
  46. ;
  47. ; VOID
  48. ; _StartPx_RMStub
  49. ;
  50. ; Routine Description:
  51. ;
  52. ; When a new processor is started, it starts in real-mode and is
  53. ; sent to a copy of this function which has been copied into low memory.
  54. ; (below 1m and accessable from real-mode).
  55. ;
  56. ; Once CR0 has been set, this function jmp's to a StartPx_PMStub
  57. ;
  58. ; Arguments:
  59. ; none
  60. ;
  61. ; Return Value:
  62. ; does not return, jumps to StartPx_PMStub
  63. ;
  64. ;--
  65. cPublicProc _StartPx_RMStub ,0
  66. cli
  67. db 066h ; load the GDT
  68. lgdt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrGdtr]
  69. db 066h ; load the IDT
  70. lidt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrIdtr]
  71. mov eax, cs:[SPx_TiledCR3]
  72. nop ; Fill - Ensure 13 non-page split
  73. nop ; accesses before CR3 load
  74. nop ; (P6 errata #11 stepping B0)
  75. nop
  76. nop
  77. nop
  78. nop
  79. nop
  80. nop
  81. nop
  82. nop
  83. nop
  84. mov cr3, eax
  85. ;
  86. ; Restore CR4 to enable Page Size Extensions
  87. ; before we got real CR3 which might use Large Page.
  88. ; If SrCr4 is non-zero, then CR4 exists
  89. ;
  90. mov eax, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr4]
  91. or eax, eax
  92. jz @f
  93. .586p
  94. mov cr4, eax
  95. .386p
  96. @@:
  97. mov ebp, dword ptr cs:[SPx_P0EBP]
  98. mov ecx, dword ptr cs:[SPx_PB.PsContextFrame.CsSegDs]
  99. mov ebx, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr3]
  100. mov eax, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr0]
  101. mov edi, dword ptr cs:[SPx_flat_addr]
  102. mov cr0, eax ; into prot mode
  103. db 066h
  104. db 0eah ; reload cs:eip
  105. SPrxPMStub dd 0
  106. SPrxFlatCS dw 0
  107. _StartPx_RMStub_Len equ $ - _StartPx_RMStub
  108. stdENDP _StartPx_RMStub
  109. PAGELK16 ends ; End 16 bit code
  110. PAGELK SEGMENT PARA PUBLIC 'CODE' ; Start 32 bit code
  111. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  112. ;++
  113. ;
  114. ; VOID
  115. ; StartPx_PMStub
  116. ;
  117. ; Routine Description:
  118. ;
  119. ; This function completes the processor's state loading, and signals
  120. ; the requesting processor that the state has been loaded.
  121. ;
  122. ; Arguments:
  123. ; ebx - requested CR3 for this processors_state
  124. ; cx - requested ds for this processors_state
  125. ; ebp - EBP of P0
  126. ; edi - p-mode address of startup block
  127. ;
  128. ; Return Value:
  129. ; does not return - completes the loading of the processors_state
  130. ;
  131. ;--
  132. align dword ; to make sure we don't cross a page boundry
  133. ; before reloading CR3
  134. cPublicProc _StartPx_PMStub ,0
  135. ; process is now in the load image copy of this function.
  136. ; (ie, it's not the low memory copy)
  137. mov cr3, ebx ; get real CR3
  138. mov ds, cx ; set real ds
  139. lea esi, [edi].SPx_PB.PsSpecialRegisters
  140. lldt word ptr ds:[esi].SrLdtr ; load ldtr
  141. ;
  142. ; Force the TSS descriptor into a non-busy state, so we don't fault
  143. ; when we load the TR.
  144. ;
  145. mov eax, ds:[esi].SrGdtr+2 ; (eax)->GDT base
  146. xor ecx, ecx
  147. mov cx, word ptr ds:[esi].SrTr
  148. add eax, 5
  149. add eax, ecx ; (eax)->TSS Desc. Byte
  150. and byte ptr [eax],NOT 2
  151. ltr word ptr ds:[esi].SrTr ; load tss
  152. lea edx, [edi].SPx_PB.PsContextFrame
  153. mov es, word ptr ds:[edx].CsSegEs ; Set other selectors
  154. mov fs, word ptr ds:[edx].CsSegFs
  155. mov gs, word ptr ds:[edx].CsSegGs
  156. mov ss, word ptr ds:[edx].CsSegSs
  157. cld ; make lodsd ascending (below)
  158. xor eax, eax ; disable debug registers while
  159. mov dr7, eax ; setting them.
  160. add esi, SrKernelDr0
  161. .errnz (SrKernelDr1 - SrKernelDr0 - 1 * 4)
  162. .errnz (SrKernelDr2 - SrKernelDr0 - 2 * 4)
  163. .errnz (SrKernelDr3 - SrKernelDr0 - 3 * 4)
  164. .errnz (SrKernelDr6 - SrKernelDr0 - 4 * 4)
  165. .errnz (SrKernelDr7 - SrKernelDr0 - 5 * 4)
  166. lodsd
  167. mov dr0, eax ; load dr0-dr7
  168. lodsd
  169. mov dr1, eax
  170. lodsd
  171. mov dr2, eax
  172. lodsd
  173. mov dr3, eax
  174. lodsd
  175. mov dr6, eax
  176. lodsd
  177. mov dr7, eax
  178. mov esp, dword ptr ds:[edx].CsEsp
  179. mov ecx, dword ptr ds:[edx].CsEcx
  180. push dword ptr ds:[edx].CsEflags
  181. popfd ; load eflags
  182. push dword ptr ds:[edx].CsEip ; make a copy of remaining
  183. push dword ptr ds:[edx].CsEax ; registers which need
  184. push dword ptr ds:[edx].CsEbx ; loaded
  185. push dword ptr ds:[edx].CsEdx
  186. push dword ptr ds:[edx].CsEsi
  187. push dword ptr ds:[edx].CsEdi
  188. push dword ptr ds:[edx].CsEbp
  189. inc [edi.SPx_flag] ; Signal p0 that we are
  190. ; done with it's data
  191. ; Set remaining registers
  192. pop ebp
  193. pop edi
  194. pop esi
  195. pop edx
  196. pop ebx
  197. pop eax
  198. stdRET _StartPx_PMStub
  199. stdENDP _StartPx_PMStub
  200. ;++
  201. ;
  202. ; VOID
  203. ; StartPx_BuildRealModeStart(
  204. ; IN PUCHAR ParamBlock
  205. ; )
  206. ;
  207. ; Routine Description:
  208. ;
  209. ; This function sets up the real mode startup page
  210. ;
  211. ; Arguments:
  212. ;
  213. ; PxParamBlock -- address of the structure that should end up
  214. ; at the beginning of HalpLowStub
  215. ;
  216. ;--
  217. ParamBlockAddress equ [ebp + 8]
  218. cPublicProc _StartPx_BuildRealModeStart ,1
  219. push ebp
  220. mov ebp, esp
  221. push ebx
  222. push esi
  223. push edi
  224. mov edx, ParamBlockAddress
  225. ;
  226. ; Build a jmp to the start of the Real mode startup code
  227. ;
  228. ; This is needed because the Local APIC implementations
  229. ; use a Startup IPI that must be Page aligned. The allocation
  230. ; code int MP_INIT ensures that this is page aligned. The
  231. ; original code was written to place the parameter block first.
  232. ; By adding a jump instruction to the start of the parameter block
  233. ; we can run either way.
  234. ;
  235. mov eax, size PxParamBlock - 3 ; Jump destination relative to
  236. ; next instruction
  237. shl eax, 8 ; Need room for jmp instruction
  238. mov al,0e9h
  239. mov [edx].SPx_Jmp_Inst, eax
  240. ;
  241. ; Save the p-mode address of PxParamBlock
  242. ;
  243. mov eax, _HalpLowStub
  244. mov [edx].SPx_flat_addr, eax
  245. ;
  246. ; Copy RMStub to low memory
  247. ;
  248. mov esi, OFFSET FLAT:_StartPx_RMStub
  249. mov ecx, _StartPx_RMStub_Len
  250. mov edi, _HalpLowStub ; Destination was allocated by MpInit
  251. add edi, size PxParamBlock ; Parameter Block is placed first
  252. rep movsb
  253. ;
  254. ; Copy the parameter block to low memory
  255. ;
  256. mov ecx, size PxParamBlock ; Structure length
  257. mov esi, ParamBlockAddress ; Parameter Block is placed first
  258. mov edi, _HalpLowStub ; Destination Address
  259. rep movsb
  260. ;
  261. ; Now we need to create a pointer allowing the Real Mode code to
  262. ; Branch to the Protected mode code
  263. ;
  264. mov eax, _HalpLowStub ; low memory Address
  265. add eax, size PxParamBlock ; Move past the Parameter block
  266. ;
  267. ; In order to get to the label we need to compute the label offset relative
  268. ; to the start of the routine and then use this as a offset from the start of
  269. ; the routine ( HalpLowStub + (size PxParamBlock)) in low memory.
  270. ;
  271. ; The following code creates a pointer to (RMStub - StartPx_RMStub)
  272. ; which can then be used to access code locations via code labels directly.
  273. ; Since the [eax.Label] results in the address (eax + Label) loading eax
  274. ; with the pointer created above results in (RMStub - StartPx_RMStub + Label).
  275. ;
  276. mov ebx, OFFSET FLAT:_StartPx_RMStub
  277. sub eax, ebx ; (eax) = adjusted pointer
  278. ;
  279. ; Patch the real mode code with a valid long jump address, first CS then offset
  280. ;
  281. mov bx, word ptr [edx].SPx_PB.PsContextFrame.CsSegCs
  282. mov [eax.SPrxFlatCS], bx
  283. mov [eax.SPrxPMStub], offset _StartPx_PMStub
  284. pop edi
  285. pop esi
  286. pop ebx
  287. pop ebp
  288. stdRET _StartPx_BuildRealModeStart
  289. stdENDP _StartPx_BuildRealModeStart
  290. subttl "Save Processor State"
  291. ;++
  292. ;
  293. ; VOID
  294. ; HalpSaveProcessorStateAndWait(
  295. ; IN PKPROCESSOR_STATE ProcessorState
  296. ; )
  297. ;
  298. ; Routine Description:
  299. ;
  300. ; This function saves the volatile, non-volatile and special register
  301. ; state of the current processor.
  302. ;
  303. ; N.B. Floating point state is NOT captured.
  304. ;
  305. ; Arguments:
  306. ;
  307. ; ProcessorState (esp+4) - Address of processor state record to fill in.
  308. ;
  309. ; pBarrier - Address of a value to use as a lock.
  310. ;
  311. ; Return Value:
  312. ;
  313. ; None. This function does not return.
  314. ;
  315. ;--
  316. ProcessorState equ [esp + 8]
  317. pBarrier equ dword ptr [esp + 12]
  318. cPublicProc _HalpSaveProcessorStateAndWait,2
  319. push ebx
  320. mov ebx, ProcessorState
  321. cmp ebx, 0 ; if this isn't filled in, don't save context
  322. jz hspsaw_statesaved
  323. ;
  324. ; Fill in ProcessorState
  325. ;
  326. push ebx
  327. call _KeSaveStateForHibernate ; _cdecl function
  328. add esp, 4
  329. ;; Save return address, not caller's return address
  330. mov eax,[esp+4]
  331. mov [ebx.PsContextFrame.CsEip],eax
  332. ;; Save caller's ebp, not caller's return ebp.
  333. mov [ebx.PsContextFrame.CsEbp],ebp
  334. ;; Set ESP to value just before this function call
  335. lea eax,[esp+16]
  336. mov [ebx.PsContextFrame.CsEsp],eax
  337. hspsaw_statesaved:
  338. ifdef ACPI_HAL
  339. ;
  340. ; Flush the cache, as the processor may be about
  341. ; to power off.
  342. ;
  343. fstCall HalpAcpiFlushCache
  344. endif
  345. ;
  346. ; Signal that this processor has saved its state
  347. ;
  348. mov ebx, pBarrier
  349. lock inc dword ptr [ebx]
  350. ;
  351. ; Wait for the hibernation file to be written.
  352. ; Processor 0 will zero Barrier when it is
  353. ; finished.
  354. ;
  355. ; N.B. We can't return from this function
  356. ; before the hibernation file is finished
  357. ; because we would be tearing down the very same
  358. ; stack that we will be jumping onto when the
  359. ; processor resumes. But after the hibernation
  360. ; file is written, it doesn't matter, because
  361. ; the stack will be restored from disk.
  362. ;
  363. hspsaw_spin:
  364. YIELD
  365. cmp dword ptr [ebx], 0
  366. jne hspsaw_spin
  367. ;
  368. ; Invalidate the processor cache so that any stray gamma
  369. ; rays (I'm serious) that may have flipped cache bits
  370. ; while in S1 will be ignored.
  371. ;
  372. ; Honestly. Intel asked for this. I'm serious.
  373. ;
  374. ;.586
  375. ; invd
  376. ;.386
  377. pop ebx
  378. stdRET _HalpSaveProcessorStateAndWait
  379. stdENDP _HalpSaveProcessorStateAndWait
  380. PAGELK ends ; end 32 bit code
  381. end