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.

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