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.

731 lines
18 KiB

  1. title "Sleep Handlers"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; ixsstate.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements the code for putting the machine to
  13. ; sleep.
  14. ;
  15. ; Author:
  16. ;
  17. ; Jake Oshins (jakeo) March 13, 1997
  18. ;
  19. ; Environment:
  20. ;
  21. ; Kernel mode only.
  22. ;
  23. ; Revision History:
  24. ;
  25. ;--
  26. .386p
  27. .xlist
  28. include hal386.inc
  29. include callconv.inc ; calling convention macros
  30. include i386\ix8259.inc
  31. include i386\kimacro.inc
  32. include mac386.inc
  33. include i386\ixcmos.inc
  34. include xxacpi.h
  35. include i386\ixslpctx.inc
  36. .list
  37. EXTRNP _HalpAcpiPreSleep ,1
  38. EXTRNP _HalpAcpiPostSleep ,1
  39. EXTRNP _HalpPostSleepMP, 2
  40. EXTRNP _HalpReenableAcpi, 0
  41. EXTRNP _StartPx_BuildRealModeStart,1
  42. EXTRNP KfLowerIrql, 1,,FASTCALL
  43. EXTRNP _KeGetCurrentIrql,0
  44. EXTRNP _HalpSaveProcessorStateAndWait,2
  45. EXTRNP _KeStallExecutionProcessor, 1
  46. EXTRNP _HalpClearSlpSmiStsInICH,0
  47. EXTRNP _HalpWakeupTimeElapsed,0
  48. extrn _HalpLowStubPhysicalAddress:DWORD
  49. extrn _KeSaveStateForHibernate:proc
  50. extrn _HalpFixedAcpiDescTable:DWORD
  51. extrn _HalpWakeVector:DWORD
  52. extrn _HalpTiledCr3Addresses:DWORD
  53. extrn _HalpVirtAddrForFlush:DWORD
  54. extrn _HalpPteForFlush:DWORD
  55. extrn _HalpHiberProcState:DWORD
  56. extrn _HalpBroken440BX:byte
  57. _DATA SEGMENT DWORD PUBLIC 'DATA'
  58. ALIGN dword
  59. public HalpSleepSync
  60. HalpSleepSync dd 0
  61. public HalpBarrier
  62. HalpBarrier dd 0
  63. _DATA ends
  64. PAGELK SEGMENT DWORD PUBLIC 'CODE'
  65. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  66. page ,132
  67. subttl "Sleep Handlers"
  68. ; VOID
  69. ; FASTCALL
  70. ; HalpAcpiFlushCache(
  71. ; VOID
  72. ; )
  73. ; /*++
  74. ;
  75. ; Routine Description:
  76. ;
  77. ; This is called to flush everything from the caches.
  78. ;
  79. ; Arguments:
  80. ;
  81. ; none
  82. ;
  83. ; Return Value:
  84. ;
  85. ; none
  86. ;
  87. ; --*/
  88. ;
  89. ; eax - offset within a page
  90. ; ebx - stride size
  91. ; ecx - address of PTE we are manipulating
  92. ; edi - Physical Address of page
  93. ; esi - Virtual Address of page used for flush
  94. ; ebp - Flush Limit
  95. ;
  96. FlushBase equ 100000h
  97. PageLength equ 4096
  98. PteValid equ 1
  99. PteWrite equ 2
  100. PteAccessed equ 20h
  101. PteDirty equ 40h
  102. PteBits equ (PteValid or PteWrite)
  103. cPublicFastCall HalpAcpiFlushCache, 0
  104. cPublicFpo 0, 0
  105. mov eax, [FADT_FLAGS]
  106. test eax, WBINVD_SUPPORTED or WBINVD_FLUSH
  107. jz short hafc10
  108. .586p
  109. wbinvd
  110. fstRET HalpAcpiFlushCache
  111. hafc10:
  112. push ebp
  113. push ebx
  114. push esi
  115. push edi
  116. movzx eax, word ptr [FLUSH_STRIDE]
  117. mov ebx, eax ; save the stride size
  118. movzx ecx, word ptr [FLUSH_SIZE]
  119. mul ecx
  120. add eax, FlushBase
  121. mov ebp, eax ; ebp <- ending physical address
  122. ;
  123. ; Iterate across all cache lines
  124. ;
  125. mov edi, FlushBase ; start at 1MB, physical
  126. mov esi, [_HalpVirtAddrForFlush]
  127. mov ecx, [_HalpPteForFlush]
  128. hafc20:
  129. ; put the right physical page into the PTE
  130. mov edx, PteBits ; mask off the page
  131. or edx, edi
  132. mov [ecx], edx
  133. invlpg [esi]
  134. add edi, PageLength ; next physical page
  135. xor eax, eax
  136. ; flush a cache line
  137. hafc30: mov edx, [esi][eax]
  138. add eax, ebx
  139. cmp eax, PageLength
  140. jl short hafc30
  141. cmp edi, ebp
  142. jl short hafc20
  143. pop edi
  144. pop esi
  145. pop ebx
  146. pop ebp
  147. .386p
  148. fstRET HalpAcpiFlushCache
  149. fstENDP HalpAcpiFlushCache
  150. ;++
  151. ; UCHAR
  152. ; FASTCALL
  153. ; HalpSetup440BXWorkaround(
  154. ; )
  155. ;
  156. ; Routine Description:
  157. ;
  158. ; This function provides part of the workaround for
  159. ; broken 440BX chips.
  160. ;
  161. ; Arguments:
  162. ;
  163. ; none
  164. ;
  165. ; Return Value:
  166. ;
  167. ; the previous contents of 440BX DRAM Control Register (57h)
  168. ;
  169. ;--
  170. cPublicFastCall HalpSetup440BXWorkaround, 0
  171. cPublicFpo 0,0
  172. mov dx, 0cf8h
  173. mov eax, 80000054h
  174. out dx, eax
  175. mov dx, 0cffh
  176. in al, dx
  177. mov cl, al
  178. or al, 7
  179. out dx, al
  180. push ecx
  181. stdCall _KeStallExecutionProcessor <15>
  182. pop ecx
  183. mov dx, 0cf8h
  184. mov eax, 80000054h
  185. out dx, eax
  186. mov dx, 0cffh
  187. in al, dx
  188. and al, 0f8h
  189. out dx, al
  190. movzx eax, cl
  191. fstRET HalpSetup440BXWorkaround
  192. fstENDP HalpSetup440BXWorkaround
  193. ;++
  194. ; VOID
  195. ; FASTCALL
  196. ; HalpComplete440BXWorkaround(
  197. ; UCHAR DramControl
  198. ; )
  199. ;
  200. ; Routine Description:
  201. ;
  202. ; This function provides the other part of the workaround for
  203. ; broken 440BX chips.
  204. ;
  205. ; Arguments:
  206. ;
  207. ; the previous contents of 440BX DRAM Control Register (57h)
  208. ;
  209. ; Return Value:
  210. ;
  211. ; none
  212. ;
  213. ;--
  214. cPublicFastCall HalpComplete440BXWorkaround, 1
  215. cPublicFpo 0,0
  216. mov dx, 0cf8h
  217. mov eax, 80000054h
  218. out dx, eax
  219. mov dx, 0cffh
  220. mov al, cl
  221. out dx, al
  222. fstRET HalpComplete440BXWorkaround
  223. fstENDP HalpComplete440BXWorkaround
  224. ; NTSTATUS
  225. ; HaliAcpiSleep(
  226. ; IN PVOID Context,
  227. ; IN PENTER_STATE_SYSTEM_HANDLER SystemHandler OPTIONAL,
  228. ; IN PVOID SystemContext,
  229. ; IN LONG NumberProcessors,
  230. ; IN volatile PLONG Number
  231. ; )
  232. ; /*++
  233. ;
  234. ; Routine Description:
  235. ;
  236. ; This is called by the Policy Manager to enter Sx.
  237. ;
  238. ; Arguments:
  239. ;
  240. ; Context - unused
  241. ;
  242. ; NumberProcessors - currently unused
  243. ;
  244. ; Number - currently unused
  245. ;
  246. ; Return Value:
  247. ;
  248. ; none
  249. ;
  250. ; --*/
  251. Context equ [ebp+8]
  252. SysHandler equ [ebp+12]
  253. SysContext equ [ebp+16]
  254. NumberProc equ [ebp+20]
  255. Barrier equ [ebp+24]
  256. Pm1aEvt equ [ebp-4]
  257. Pm1bEvt equ [ebp-8]
  258. Status equ [ebp-12]
  259. SlpTypA equ [ebp-14]
  260. SlpTypB equ [ebp-16]
  261. ThisProc equ [ebp-20]
  262. OldIrql equ [ebp-24]
  263. PrevDRAM equ [ebp-28]
  264. FrameSize equ 28
  265. cPublicProc _HaliAcpiSleep, 5
  266. cPublicFpo 5, 4
  267. push ebp
  268. mov ebp, esp
  269. sub esp, FrameSize
  270. push ebx
  271. push esi
  272. push edi
  273. pushfd
  274. cli
  275. mov edi, HalpSleepSync ; Get current sleep sync value
  276. xor eax, eax
  277. mov Status, eax
  278. ;
  279. ; Get current IRQL
  280. ;
  281. stdCall _KeGetCurrentIrql
  282. mov OldIrql, eax
  283. ;
  284. ; Send all
  285. ;
  286. mov al, PCR[PcNumber]
  287. or al, al ; Is this processor 0?
  288. jnz has_wait ; if not, set it waiting
  289. mov HalpBarrier, 0 ; init Barrier, processor 0 does it
  290. ;
  291. ; Make sure the other processors have saved their
  292. ; state and begun to spin.
  293. ;
  294. lock inc [HalpSleepSync] ; account for this proc
  295. has1: YIELD
  296. mov eax, [HalpSleepSync]
  297. cmp eax, NumberProc
  298. jnz short has1
  299. ;
  300. ; Take care of chores (RTC, interrupt controller, etc.)
  301. stdCall _HalpAcpiPreSleep, <Context>
  302. or al, al ; check for failure
  303. jz has_slept ; if FALSE, then don't sleep at all
  304. ;
  305. ; If we will be losing processor state, save it
  306. ;
  307. mov eax, Context
  308. test eax, SLEEP_STATE_FIRMWARE_RESTART shl CONTEXT_FLAG_SHIFT
  309. jz short has2
  310. lea eax, haswake
  311. stdCall _HalpSetupRealModeResume, <eax>
  312. ;
  313. ; Record the values in the SLP_TYP registers
  314. ;
  315. has2:
  316. mov edx, [PM1a_CNT]
  317. in ax, dx
  318. mov SlpTypA, ax
  319. mov edx, [PM1b_CNT]
  320. or edx, edx
  321. jz short has5
  322. in ax, dx
  323. mov SlpTypB, ax
  324. has5:
  325. ;
  326. ; The hal has all of it's state saved into ram and is ready
  327. ; for the power down. If there's a system state handler give
  328. ; it a shot
  329. ;
  330. mov ebx, SysHandler
  331. or ebx, ebx
  332. jz short has10
  333. mov ecx, SysContext
  334. push ecx
  335. call ebx ; Call the system state handler
  336. mov Status, eax
  337. test eax, eax
  338. jnz has_s4_wake ; If not success, exit
  339. ;
  340. ; Check the RTC one last time in case it expired while we were writing
  341. ; out the Hiberfile.
  342. ;
  343. stdCall _HalpWakeupTimeElapsed
  344. or eax, eax
  345. jnz has_s4_wake ; If expired, exit
  346. has10:
  347. mov esi, Context
  348. mov edx, [PM1a_EVT]
  349. mov ecx, [PM1b_EVT]
  350. or ecx, ecx
  351. jnz short has20
  352. mov ecx, edx
  353. has20:
  354. mov Pm1aEvt, ecx
  355. mov Pm1bEvt, edx ; save PM1a_EVT & PM1b_EVT address
  356. ;
  357. ; Reset WAK_STS
  358. ;
  359. mov eax, WAK_STS
  360. out dx, ax ; clear PM1a WAK_STS
  361. mov edx, ecx
  362. out dx, ax ; clear PM1b WAK_STS
  363. ;
  364. ; Flush the caches if necessary
  365. ;
  366. mov eax, SLEEP_STATE_FLUSH_CACHE shl CONTEXT_FLAG_SHIFT
  367. test eax, esi
  368. jz short @f
  369. fstCall HalpAcpiFlushCache
  370. @@:
  371. ;
  372. ; Work around 440BX bug. Criteria is that we have one of
  373. ; the broken BX parts and we are not hibernating, which
  374. ; we know because the SysHandler is 0.
  375. ;
  376. mov eax, SysHandler
  377. .if (_HalpBroken440BX && (eax == 0))
  378. fstCall HalpSetup440BXWorkaround
  379. movzx eax, al
  380. mov PrevDRAM, eax
  381. .endif
  382. ;
  383. ; Issue SLP commands to PM1a_CNT and PM1b_CNT
  384. ;
  385. mov edx, [PM1a_CNT]
  386. mov ecx, esi
  387. and ecx, 0fh ; nibble 0 is 1a sleep type
  388. shl ecx, SLP_TYP_SHIFT ; put it in position
  389. or ecx, SLP_EN ; enable sleep ********
  390. in ax, dx
  391. and ax, CTL_PRESERVE ; preserve some bits
  392. or ax, cx
  393. out dx, ax
  394. mov edx, [PM1b_CNT]
  395. or edx, edx
  396. jz short has30
  397. mov ecx, esi
  398. and ecx, 0f0h ; nibble 1 is 1b sleep type
  399. shl ecx, (SLP_TYP_SHIFT-4) ; put it in position
  400. or ecx, SLP_EN ; enable sleep *********
  401. in ax, dx
  402. and ax, CTL_PRESERVE ; preserve some bits
  403. or ax, cx
  404. out dx, ax
  405. has30:
  406. ;
  407. ; Wait for sleep to be over
  408. ;
  409. mov ecx, Pm1bEvt
  410. mov edx, Pm1aEvt ; retrieve PM1_EVT & PM1b_EVT
  411. has40: in ax, dx
  412. test ax, WAK_STS
  413. xchg edx, ecx
  414. jz short has40
  415. ;
  416. ; Finish 440BX workaround
  417. ;
  418. mov eax, SysHandler
  419. .if (_HalpBroken440BX && (eax == 0))
  420. mov ecx, PrevDRAM
  421. fstCall HalpComplete440BXWorkaround
  422. .endif
  423. ;
  424. ; Invalidate the processor cache so that any stray gamma
  425. ; rays (I'm serious) that may have flipped cache bits
  426. ; while in S1 will be ignored.
  427. ;
  428. ; Honestly. Intel asked for this. I'm serious.
  429. ;
  430. ;.586
  431. ; invd
  432. ;.386
  433. haswake:
  434. ;
  435. ; Hack around ICH2/ASUS BIOS.
  436. ;
  437. stdCall _HalpClearSlpSmiStsInICH
  438. ;
  439. ; Restore the SLP_TYP registers. (So that embedded controllers
  440. ; and BIOSes can be sure that we think the machine is awake.)
  441. ;
  442. mov edx, [PM1a_CNT]
  443. mov ax, SlpTypA
  444. out dx, ax
  445. mov edx, [PM1b_CNT]
  446. or edx, edx
  447. jz short has_slept
  448. mov ax, SlpTypB
  449. out dx, ax
  450. has_slept:
  451. stdCall _HalpAcpiPostSleep, <Context>
  452. ;
  453. ; Notify other processor of completion
  454. ;
  455. mov HalpSleepSync, 0
  456. jmp short has_90
  457. has_wait:
  458. xor eax, eax
  459. mov edx, Context
  460. test edx, SLEEP_STATE_OFF shl CONTEXT_FLAG_SHIFT
  461. jnz has_wait2 ; if going to S5, don't save context
  462. mov al, PCR[PcNumber] ; get processor number
  463. mov edx, ProcessorStateLength ; get size of proc state
  464. mul dx ; generate an index into HalpHiberProcState
  465. add eax, _HalpHiberProcState ; add the index to base
  466. has_wait2:
  467. lea edx, HalpSleepSync
  468. stdCall _HalpSaveProcessorStateAndWait <eax, edx>
  469. ;
  470. ; Wait for next phase
  471. ;
  472. hasw10: YIELD
  473. cmp HalpSleepSync, 0 ; wait for barrier to move
  474. jne short hasw10
  475. ;
  476. ; All phases complete, exit
  477. ;
  478. has_90:
  479. ;
  480. ; Restore each processor's APIC state.
  481. ;
  482. lea eax, HalpBarrier
  483. stdCall _HalpPostSleepMP <NumberProc, eax>
  484. ;
  485. ; Restore caller's IRQL
  486. ;
  487. mov ecx, OldIrql
  488. fstCall KfLowerIrql
  489. ;
  490. ; Exit
  491. ;
  492. mov HalpSleepSync, 0
  493. mov eax, Status
  494. popfd
  495. pop edi
  496. pop esi
  497. pop ebx
  498. mov esp, ebp
  499. pop ebp
  500. stdRET _HaliAcpiSleep
  501. has_s4_wake:
  502. stdCall _HalpReenableAcpi
  503. jmp haswake
  504. stdENDP _HaliAcpiSleep
  505. ;++
  506. ;
  507. ; BOOLEAN
  508. ; HalpSetupRealModeResume (
  509. ; )
  510. ;
  511. ; Routine Description:
  512. ;
  513. ; This routine is called by the kernel durning kernel initialization
  514. ; to obtain more processors. It is called until no more processors
  515. ; are available.
  516. ;
  517. ; If another processor exists this function is to initialize it to
  518. ; the passed in processorstate structure, and return TRUE.
  519. ;
  520. ; If another processor does not exists or if the processor fails to
  521. ; start, then a FALSE is returned.
  522. ;
  523. ; Also note that the loader block has been setup for the next processor.
  524. ; The new processor logical thread number can be obtained from it, if
  525. ; required.
  526. ;
  527. ; In order to use the Startup IPI the real mode startup code must be
  528. ; page aligned. The MpLowStubPhysicalAddress has always been page
  529. ; aligned but because the PxParamBlock was placed first in this
  530. ; segment the real mode code has been something other than page aligned.
  531. ; This has been changed by making the first entry in the PxParamBlock
  532. ; a jump instruction to the real mode startup code.
  533. ;
  534. ; Arguments:
  535. ;
  536. ; WakeupReturnAddress - address that processor should return to
  537. ; after it has been asleep
  538. ;
  539. ; Return Value:
  540. ;
  541. ;
  542. ;--
  543. WakeupReturnAddress equ dword ptr [ebp + 20]
  544. ;
  545. ; Local variables
  546. ;
  547. PxFrame equ [ebp - size PxParamBlock]
  548. LWarmResetVector equ [ebp - size PxParamBlock - 4]
  549. LStatusCode equ [ebp - size PxParamBlock - 8]
  550. LCmosValue equ [ebp - size PxParamBlock - 12]
  551. CallingEbp equ [ebp]
  552. CallingEsi equ [ebp + 12]
  553. CallingEdi equ [ebp + 8]
  554. CallingEbx equ [ebp + 4]
  555. CallingEsp equ 24 ; relative to current ebp
  556. cPublicProc _HalpSetupRealModeResume ,1
  557. cPublicFpo 4, 80
  558. push esi ; Save required registers
  559. push edi
  560. push ebx
  561. push ebp ; save ebp
  562. mov ebp, esp ; Save Frame
  563. sub esp, size PxParamBlock + 12 ; Make room for local vars
  564. xor eax, eax
  565. mov LStatusCode, eax
  566. ;
  567. ; Fill in the firmware wakeup vector
  568. ;
  569. mov eax, _HalpLowStubPhysicalAddress
  570. mov ecx, [_HalpWakeVector]
  571. mov [ecx], eax
  572. ;
  573. ; Save the processor context
  574. ;
  575. lea edi, PxFrame.SPx_PB
  576. push edi
  577. call _KeSaveStateForHibernate ; _cdecl function
  578. add esp, 4
  579. ;
  580. ; Get a CR3 for the starting processor
  581. ;
  582. mov eax, [_HalpTiledCr3Addresses] ; the low 32-bits of processor 0's CR3
  583. mov eax, [eax] ; physical address will be here
  584. mov PxFrame.SPx_TiledCR3, eax ; Newly contructed CR3
  585. mov PxFrame.SPx_P0EBP, ebp ; Stack pointer
  586. lea edi, PxFrame.SPx_PB.PsContextFrame
  587. mov eax, WakeupReturnAddress
  588. mov dword ptr [edi].CsEip, eax ; make a copy of remaining
  589. mov eax, CallingEbx ; registers which need
  590. mov dword ptr [edi].CsEbx, eax ; loaded
  591. mov eax, CallingEsi
  592. mov dword ptr [edi].CsEsi, eax
  593. mov eax, CallingEdi
  594. mov dword ptr [edi].CsEdi, eax
  595. mov eax, CallingEbp
  596. mov dword ptr [edi].CsEbp, eax
  597. mov eax, ebp
  598. add eax, CallingEsp
  599. mov dword ptr [edi].CsEsp, eax
  600. lea eax, PxFrame
  601. stdCall _StartPx_BuildRealModeStart, <eax>
  602. snp_exit:
  603. mov esp, ebp
  604. pop ebp
  605. pop ebx
  606. pop edi
  607. pop esi
  608. stdRET _HalpSetupRealModeResume
  609. stdENDP _HalpSetupRealModeResume
  610. PAGELK ends
  611. end