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.

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