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.

677 lines
18 KiB

  1. ;++
  2. ;
  3. ;Copyright (c) 1997 Microsoft Corporation
  4. ;
  5. ;Module Name:
  6. ;
  7. ; wakea.asm
  8. ;
  9. ;Abstract:
  10. ;
  11. ;
  12. ;Author:
  13. ;
  14. ; Ken Reneris (kenr) 05-May-1997
  15. ;
  16. ;Revision History:
  17. ;
  18. ; Steve Deng (sdeng) 20-Aug-2002
  19. ;
  20. ; Support hibernation in PAE mode. It is assumed that all the
  21. ; physical pages are below 4GB. Otherwise hibernation feature
  22. ; should be disabled.
  23. ;--
  24. .586p
  25. .xlist
  26. include ks386.inc
  27. include callconv.inc ; calling convention macros
  28. .list
  29. extrn _HiberPtes:DWORD
  30. extrn _HiberVa:DWORD
  31. extrn _HiberFirstRemap:DWORD
  32. extrn _HiberLastRemap:DWORD
  33. extrn _HiberPageFrames:DWORD
  34. extrn _HiberTransVa:DWORD
  35. extrn _HiberIdentityVa:DWORD
  36. extrn _HiberImageFeatureFlags:DWORD
  37. extrn _HiberBreakOnWake:BYTE
  38. extrn _HiberImagePageSelf:DWORD
  39. extrn _BlUsePae:DWORD
  40. extrn _HiberNoExecute:DWORD
  41. EXTRNP _BlpEnablePAE,1
  42. DBGOUT macro Value
  43. ; push edx
  44. ; push eax
  45. ; mov edx, 80h
  46. ; mov al, Value
  47. ; out dx, al
  48. ; pop eax
  49. ; pop edx
  50. endm
  51. ; These equates must match the defines in po.h
  52. XPRESS_MAX_PAGES equ 16
  53. ;
  54. ; These equates must match the defines in bldr.h
  55. ;
  56. PTE_SOURCE equ 0
  57. PTE_DEST equ 1
  58. PTE_MAP_PAGE equ 2
  59. PTE_REMAP_PAGE equ 3
  60. PTE_HIBER_CONTEXT equ 4
  61. PTE_TRANSFER_PDE equ 5
  62. PTE_WAKE_PTE equ 6
  63. PTE_DISPATCHER_START equ 7
  64. PTE_XPRESS_DEST_FIRST equ 9
  65. PTE_XPRESS_DEST_LAST equ (PTE_XPRESS_DEST_FIRST + XPRESS_MAX_PAGES)
  66. HIBER_PTES equ (16 + XPRESS_MAX_PAGES)
  67. ;
  68. ; Processor paging defines
  69. ;
  70. PAGE_SIZE equ 4096
  71. PAGE_SHIFT equ 12
  72. PAGE_MASK equ (PAGE_SIZE - 1)
  73. PTE_VALID equ 23h
  74. PDPT_SHIFT_PAE equ 30
  75. PDE_SHIFT_PAE equ 21
  76. PTE_SHIFT_PAE equ 12
  77. PDE_INDEX_MASK_PAE equ 1ffh
  78. PTE_INDEX_MASK_PAE equ 1ffh
  79. PDE_SHIFT equ 22
  80. PTE_SHIFT equ 12
  81. PTE_INDEX_MASK equ 3ffh
  82. ;
  83. ; Internal defines and structures
  84. ;
  85. STACK_SIZE equ 1024
  86. HbGdt struc
  87. Limit dw ?
  88. Base dd ?
  89. Pad dw ?
  90. HbGdt ends
  91. HbContextBlock struc
  92. WakeContext db processorstatelength dup (?)
  93. OldEsp dd ?
  94. PteVa dd ?
  95. TransCr3 dd ?
  96. TransPteVa dd ?
  97. WakeHiberVa dd ?
  98. Buffer dd ?
  99. MapIndex dd ?
  100. LastMapIndex dd ?
  101. FeatureFlags dd ?
  102. BlUsePae dd ?
  103. NoExecute dd ?
  104. Gdt db size HbGdt dup (?)
  105. Stack db STACK_SIZE dup (?)
  106. BufferData db ? ; buffer starts here
  107. HbContextBlock ends
  108. ;
  109. ; Addresses based from ebp
  110. ;
  111. SourcePage equ [ebp + PAGE_SIZE * PTE_SOURCE]
  112. DestPage equ [ebp + PAGE_SIZE * PTE_DEST]
  113. Map equ [ebp + PAGE_SIZE * PTE_MAP_PAGE]
  114. Remap equ [ebp + PAGE_SIZE * PTE_REMAP_PAGE]
  115. Context equ [ebp + PAGE_SIZE * PTE_HIBER_CONTEXT].HbContextBlock
  116. _TEXT SEGMENT PARA PUBLIC 'CODE' ; Start 32 bit code
  117. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  118. ;++
  119. ;
  120. ; VOID
  121. ; WakeDispatch (
  122. ; )
  123. ;
  124. ; Routine Description:
  125. ;
  126. ; Relocatable code which copies any remap page to it's final resting
  127. ; place and then restores the processors wake context.
  128. ;
  129. ; Arguments:
  130. ;
  131. ; Return
  132. ;
  133. ; Only returns if there's an internal failure
  134. ;
  135. ;--
  136. cPublicProc _WakeDispatcher, 0
  137. public _WakeDispatcherStart
  138. _WakeDispatcherStart label dword
  139. push ebp
  140. push ebx
  141. push esi
  142. push edi
  143. ;
  144. ; Load EBP with base of hiber va. Everything will be relative from EBP
  145. ;
  146. mov ebp, _HiberVa
  147. ;
  148. ; Initialize HbContextBlock
  149. ;
  150. mov eax, _HiberFirstRemap
  151. mov ecx, _HiberLastRemap
  152. lea edx, Context.BufferData
  153. mov esi, _HiberPtes
  154. mov Context.MapIndex, eax
  155. mov Context.LastMapIndex, ecx
  156. mov Context.OldEsp, esp
  157. mov Context.Buffer, edx
  158. mov Context.PteVa, esi
  159. mov eax, _HiberPageFrames [PTE_TRANSFER_PDE * 4]
  160. mov ecx, _HiberTransVa
  161. mov edx, _HiberIdentityVa
  162. mov esi, _BlUsePae
  163. mov Context.TransCr3, eax
  164. mov Context.TransPteVa, ecx
  165. mov Context.WakeHiberVa, edx
  166. mov Context.BlUsePae, esi
  167. mov eax, _HiberImageFeatureFlags
  168. mov ecx, _HiberNoExecute
  169. mov Context.FeatureFlags, eax
  170. mov Context.NoExecute, ecx
  171. DBGOUT 1
  172. ;
  173. ; Copy gdt to shared buffer and switch to it
  174. ;
  175. sgdt fword ptr Context.Gdt
  176. movzx ecx, Context.Gdt.Limit
  177. inc ecx
  178. push ecx
  179. call AllocateHeap
  180. pop ecx
  181. mov edi, eax
  182. mov esi, Context.Gdt.Base
  183. rep movsb
  184. mov Context.Gdt.Base, eax
  185. lgdt fword ptr Context.Gdt
  186. sub eax, ebp
  187. add eax, Context.WakeHiberVa
  188. mov Context.Gdt.Base, eax
  189. ;
  190. ; Locate hiber ptes in hibernated image. First get the PDE, then find
  191. ; the PTE for the hiber ptes.
  192. ;
  193. mov eax, dword ptr Context.WakeContext.PsSpecialRegisters.SrCr3
  194. shr eax, PAGE_SHIFT
  195. call LocatePage
  196. push eax
  197. push PTE_SOURCE
  198. call SetPte
  199. cmp Context.BlUsePae, 0 ; check if it is to restore to PAE mode
  200. jnz short @f ;
  201. mov ecx, Context.WakeHiberVa
  202. shr ecx, PDE_SHIFT ; (ecx) = index into PDE
  203. mov eax, [eax+ecx*4] ; (eax) = PDE for WakeHiberVa PTE
  204. shr eax, PAGE_SHIFT
  205. call LocatePage
  206. push eax
  207. push PTE_SOURCE
  208. call SetPte
  209. mov ecx, Context.WakeHiberVa
  210. shr ecx, PTE_SHIFT
  211. and ecx, PTE_INDEX_MASK ; (ecx) = index into PTE
  212. lea edi, [eax+ecx*4] ; (edi) = address of WakeHiber PTEs
  213. jmp short hd02
  214. @@: mov ecx, dword ptr Context.WakeContext.PsSpecialRegisters.SrCr3
  215. and ecx, 0fe0h ; (ecx) = offset to page boundary
  216. ; note in PAE mode Cr3 is aligned
  217. ; to 32-byte, not page, boundary
  218. add eax, ecx ; (eax) = base address of PDPT
  219. mov ecx, Context.WakeHiberVa
  220. shr ecx, PDPT_SHIFT_PAE ; (ecx) = index into PDPT
  221. mov eax, [eax+ecx*8] ; (eax) = PDPT entry for WakeHiberVa PDE
  222. shr eax, PAGE_SHIFT ; (eax) = page frame number
  223. call LocatePage ; locate the page described by (eax)
  224. push eax ; (eax) = page number located
  225. push PTE_SOURCE
  226. call SetPte ; map this page
  227. mov ecx, Context.WakeHiberVa
  228. shr ecx, PDE_SHIFT_PAE
  229. and ecx, PDE_INDEX_MASK_PAE ; (ecx) = index into PDE
  230. mov eax, [eax+ecx*8] ; (eax) = PDE for WakeHiberVa PTE
  231. shr eax, PAGE_SHIFT ; (eax) = page frame number
  232. call LocatePage ; locate the page described by (eax)
  233. push eax ; (eax) = page number located
  234. push PTE_SOURCE
  235. call SetPte ; map this page
  236. mov ecx, Context.WakeHiberVa
  237. shr ecx, PTE_SHIFT_PAE
  238. and ecx, PTE_INDEX_MASK_PAE ; (ecx) = index into PTE
  239. lea edi, [eax+ecx*8] ; (edi) = address of WakeHiber PTEs
  240. ;
  241. ; Copy the current HiberPtes to the wake image Ptes
  242. ;
  243. hd02: mov esi, Context.PteVa
  244. mov ecx, HIBER_PTES
  245. xor eax, eax
  246. cmp Context.BlUsePae, 0 ; check if OS was in PAE mode
  247. jnz short @f
  248. rep movsd
  249. jmp short hd04
  250. @@: movsd ; translate 32bit pte to PAE pte
  251. stosd ; assuming memory size is <= 4GB
  252. loopnz @b ; so that the high dword of PAE
  253. ; pte is set to 0
  254. ;
  255. ; If break on wake, set the image header signature in destionation
  256. ;
  257. hd04: cmp _HiberBreakOnWake, 0
  258. jz short hd05
  259. mov eax, _HiberImagePageSelf
  260. call LocatePage
  261. push eax
  262. push PTE_DEST
  263. call SetPte
  264. mov dword ptr [eax], 706B7262h ; 'brkp'
  265. ;
  266. ; Switch to transition CR3
  267. ;
  268. hd05:
  269. DBGOUT 2
  270. mov ebx, Context.WakeHiberVa
  271. mov eax, Context.TransCr3
  272. shl eax, PAGE_SHIFT
  273. cmp _BlUsePae, 1 ; check if OS was in PAE mode
  274. jnz short @f
  275. lea esp, Context.Stack + STACK_SIZE ; move stack to safe place
  276. push eax ; (eax) = the physical address of PDPT
  277. mov eax, _BlpEnablePAE@4
  278. call dword ptr eax ; switch to PAE mode
  279. cmp Context.NoExecute, 1 ; check if no-execute was enabled
  280. jnz short hd08 ; if not do nothing
  281. mov ecx, 0c0000080h ; (ecx) = address of EFER
  282. rdmsr ; read EFER
  283. or eax, 800h ; set NXE bit of EFER
  284. wrmsr ; write EFER
  285. jmp hd08
  286. @@: mov cr3, eax ; switch to transition Cr3 in non PAE case
  287. ;
  288. ; Move to wake images hiber va
  289. ;
  290. hd08: mov edi, ebx
  291. add ebx, PTE_DISPATCHER_START * PAGE_SIZE
  292. add ebx, offset hd10 - offset _WakeDispatcherStart
  293. jmp ebx
  294. hd10: mov ebp, edi
  295. mov eax, Context.TransPteVa
  296. mov Context.PteVa, eax
  297. lea esp, Context.Stack + STACK_SIZE
  298. lgdt fword ptr Context.Gdt
  299. ;
  300. ; Copy all pages to final locations
  301. ;
  302. DBGOUT 3
  303. lea ebx, [ebp + PTE_DISPATCHER_START * PAGE_SIZE]
  304. cmp Context.BlUsePae, 0
  305. jnz hd20
  306. add ebx, offset SetPte - offset _WakeDispatcherStart
  307. jmp hd25
  308. hd20: add ebx, offset SetPtePAE - offset _WakeDispatcherStart
  309. hd25: mov edx, Context.MapIndex
  310. hd30: cmp edx, Context.LastMapIndex
  311. jnc short hd40
  312. push dword ptr Map.[edx*4]
  313. push PTE_SOURCE
  314. call ebx
  315. mov esi, eax
  316. push dword ptr Remap.[edx*4]
  317. push PTE_DEST
  318. call ebx
  319. mov edi, eax
  320. mov ecx, PAGE_SIZE / 4
  321. rep movsd
  322. inc edx
  323. jmp short hd30
  324. ;
  325. ; Restore processors wake context
  326. ;
  327. hd40: DBGOUT 5
  328. lea esi, Context.WakeContext.PsSpecialRegisters
  329. mov eax, cr3 ; issue a couple of flushes
  330. mov cr3, eax ; before enabling global ptes
  331. mov cr3, eax
  332. mov eax, [esi].SrCr4
  333. test Context.FeatureFlags, KF_CR4
  334. jz short hd50
  335. mov cr4, eax
  336. hd50: mov eax, [esi].SrCr3
  337. mov cr3, eax
  338. mov ecx, [esi].SrCr0
  339. mov cr0, ecx ; on kernel's cr0
  340. DBGOUT 6
  341. mov ecx, [esi].SrGdtr+2 ; base of GDT
  342. lgdt fword ptr [esi].SrGdtr ; load gdtr (w/matching flat cs & ds selectors)
  343. lidt fword ptr [esi].SrIdtr ; load idtr
  344. lldt word ptr [esi].SrLdtr ; load ldtr
  345. movzx eax, word ptr [esi].SrTr ; tss selector
  346. and byte ptr [eax+ecx+5], 0fdh ; clear the busy bit in the TSS
  347. ltr ax ; load tr
  348. mov ds, word ptr Context.WakeContext.PsContextFrame.CsSegDs
  349. mov es, word ptr Context.WakeContext.PsContextFrame.CsSegEs
  350. mov fs, word ptr Context.WakeContext.PsContextFrame.CsSegFs
  351. mov gs, word ptr Context.WakeContext.PsContextFrame.CsSegGs
  352. mov ss, word ptr Context.WakeContext.PsContextFrame.CsSegSs
  353. mov ebx, dword ptr Context.WakeContext.PsContextFrame.CsEbx
  354. mov ecx, dword ptr Context.WakeContext.PsContextFrame.CsEcx
  355. mov edx, dword ptr Context.WakeContext.PsContextFrame.CsEdx
  356. mov edi, dword ptr Context.WakeContext.PsContextFrame.CsEdi
  357. mov esp, dword ptr Context.WakeContext.PsContextFrame.CsEsp
  358. push dword ptr Context.WakeContext.PsContextFrame.CsEFlags
  359. movzx eax, word ptr Context.WakeContext.PsContextFrame.CsSegCs
  360. push eax
  361. push dword ptr Context.WakeContext.PsContextFrame.CsEip
  362. push dword ptr Context.WakeContext.PsContextFrame.CsEbp
  363. push dword ptr Context.WakeContext.PsContextFrame.CsEsi
  364. push dword ptr Context.WakeContext.PsContextFrame.CsEax
  365. lea esi, Context.WakeContext.PsSpecialRegisters.SrKernelDr0
  366. lodsd
  367. mov dr0, eax ; load dr0-dr7
  368. lodsd
  369. mov dr1, eax
  370. lodsd
  371. mov dr2, eax
  372. lodsd
  373. mov dr3, eax
  374. lodsd
  375. mov dr6, eax
  376. lodsd
  377. mov dr7, eax
  378. DBGOUT 7
  379. pop eax
  380. pop esi
  381. pop ebp
  382. iretd
  383. ; this exit is only used in the shared buffer overflows
  384. Abort:
  385. mov esp, Context.OldEsp
  386. pop edi
  387. pop esi
  388. pop ebx
  389. pop ebp
  390. stdRET _WakeDispatcher
  391. ;++
  392. ;
  393. ; PUCHAR
  394. ; AllocateHeap (
  395. ; IN ULONG Length passed in ECX
  396. ; )
  397. ;
  398. ; Routine Description:
  399. ;
  400. ; Allocates the specified bytes from the wake context page.
  401. ;
  402. ; N.B. This function is part of HiberDispacther.
  403. ;
  404. ; Arguments:
  405. ; ECX - Length to allocate
  406. ;
  407. ; Returns:
  408. ; EAX - Virtual address of bytes allocated
  409. ;
  410. ; Uses:
  411. ; EAX, ECX, EDX
  412. ;
  413. ;--
  414. AllocateHeap label proc
  415. mov eax, Context.Buffer
  416. mov edx, eax
  417. test eax, 01fh ; round to 32 byte boundry
  418. jz short ah20
  419. and eax, not 01fh
  420. add eax, 20h
  421. ah20: add ecx, eax
  422. mov Context.Buffer, ecx
  423. xor ecx, edx
  424. and ecx, 0ffffffffh - PAGE_MASK
  425. jnz short Abort
  426. ret
  427. ;++
  428. ;
  429. ; PUCHAR
  430. ; SetPte (
  431. ; IN ULONG PteIndex
  432. ; IN ULONG PageFrameNumber
  433. ; )
  434. ;
  435. ; Routine Description:
  436. ;
  437. ;
  438. ; N.B. This function is part of HiberDispacther.
  439. ;
  440. ; Arguments:
  441. ;
  442. ;
  443. ; Returns:
  444. ; EAX va of mapped pte
  445. ;
  446. ; Uses:
  447. ; EAX, ECX
  448. ;
  449. ;--
  450. SetPte label proc
  451. push ecx
  452. mov eax, [esp+8] ; (eax) = pte index
  453. shl eax, 2 ; * 4
  454. add eax, Context.PteVa ; + pte base
  455. mov ecx, [esp+12] ; (ecx) = page frame number
  456. shl ecx, PAGE_SHIFT
  457. or ecx, PTE_VALID
  458. mov [eax], ecx ; set the Pte
  459. mov eax, [esp+8]
  460. shl eax, PAGE_SHIFT
  461. add eax, ebp ; (eax) = va mapped by pte
  462. invlpg [eax]
  463. pop ecx
  464. ret 8
  465. ;++
  466. ;
  467. ; PUCHAR
  468. ; SetPtePAE (
  469. ; IN ULONG PteIndex
  470. ; IN ULONG PageFrameNumber
  471. ; )
  472. ;
  473. ; Routine Description:
  474. ;
  475. ; This function maps a physical page into PAE mapping structure. The
  476. ; mapping is done on a supplied pte entry.
  477. ;
  478. ; N.B. This function is part of HiberDispacther.
  479. ;
  480. ; Arguments:
  481. ;
  482. ; PteIndex - Specify a PTE in HiberPtes list
  483. ;
  484. ; PageFrameNumber - the page frame number of the page to be mapped
  485. ;
  486. ; Returns:
  487. ;
  488. ; EAX - va of mapped pte
  489. ;
  490. ; Uses:
  491. ;
  492. ; EAX, ECX
  493. ;
  494. ;--
  495. SetPtePAE label proc
  496. push ecx
  497. mov eax, [esp+8] ; (eax) = pte index
  498. shl eax, 3 ; * 8
  499. add eax, Context.PteVa ; + pte base
  500. mov ecx, [esp+12] ; (ecx) = page frame number
  501. shl ecx, PAGE_SHIFT
  502. or ecx, PTE_VALID
  503. mov [eax], ecx ; set the low dword of PAE Pte
  504. mov dword ptr [eax+4], 0 ; assuming the high dword is always 0
  505. mov eax, [esp+8] ; (eax) = pte index
  506. shl eax, PAGE_SHIFT
  507. add eax, ebp ; (eax) = va mapped by pte
  508. invlpg [eax]
  509. pop ecx
  510. ret 8
  511. ;++
  512. ;
  513. ; ULONG
  514. ; LocatePage (
  515. ; IN ULONG PageNumber passed in eax
  516. ; )
  517. ;
  518. ; Routine Description:
  519. ;
  520. ; Find the page specified by page number in the wake context.
  521. ; The pagenumber must be a valid page.
  522. ;
  523. ; N.B. This function is part of HiberDispacther.
  524. ;
  525. ; Arguments:
  526. ;
  527. ; EAX - Page frame number of the page we try to locate.
  528. ;
  529. ; Returns:
  530. ;
  531. ; EAX - Page frame number of the page which is holding the content
  532. ; of the page of interest. This number could be different from
  533. ; the incomming page number if the requested page is in the
  534. ; remap list.
  535. ;
  536. ; Uses:
  537. ;
  538. ; EAX, EDX
  539. ;
  540. ;--
  541. LocatePage label proc
  542. ;
  543. ; Scan the remap entries for this page. If it's found, get the
  544. ; source address. If it's not found, then it's already at it's
  545. ; proper address
  546. ;
  547. mov edx, Context.MapIndex
  548. dec edx
  549. lp10: inc edx
  550. cmp edx, Context.LastMapIndex
  551. jnc short lp20
  552. cmp eax, Remap.[edx*4]
  553. jnz short lp10
  554. mov eax, Map.[edx*4]
  555. lp20: ret
  556. public _WakeDispatcherEnd
  557. _WakeDispatcherEnd label dword
  558. stdENDP _WakeDispatcher
  559. _TEXT ends
  560. end