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.

526 lines
12 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. ;--
  19. .586p
  20. .xlist
  21. include ks386.inc
  22. include callconv.inc ; calling convention macros
  23. .list
  24. extrn _HiberPtes:DWORD
  25. extrn _HiberVa:DWORD
  26. extrn _HiberFirstRemap:DWORD
  27. extrn _HiberLastRemap:DWORD
  28. extrn _HiberPageFrames:DWORD
  29. extrn _HiberTransVa:DWORD
  30. extrn _HiberIdentityVa:DWORD
  31. extrn _HiberImageFeatureFlags:DWORD
  32. extrn _HiberBreakOnWake:BYTE
  33. extrn _HiberImagePageSelf:DWORD
  34. DBGOUT macro Value
  35. ; push edx
  36. ; push eax
  37. ; mov edx, 80h
  38. ; mov al, Value
  39. ; out dx, al
  40. ; pop eax
  41. ; pop edx
  42. endm
  43. ; These equates must match the defines in po.h
  44. XPRESS_MAX_PAGES equ 16
  45. ;
  46. ; These equates must match the defines in bldr.h
  47. ;
  48. PTE_SOURCE equ 0
  49. PTE_DEST equ 1
  50. PTE_MAP_PAGE equ 2
  51. PTE_REMAP_PAGE equ 3
  52. PTE_HIBER_CONTEXT equ 4
  53. PTE_TRANSFER_PDE equ 5
  54. PTE_WAKE_PTE equ 6
  55. PTE_DISPATCHER_START equ 7
  56. PTE_XPRESS_DEST_FIRST equ 9
  57. PTE_XPRESS_DEST_LAST equ (PTE_XPRESS_DEST_FIRST + XPRESS_MAX_PAGES)
  58. HIBER_PTES equ (16 + XPRESS_MAX_PAGES)
  59. ;
  60. ; Processor paging defines
  61. ;
  62. PAGE_SIZE equ 4096
  63. PAGE_SHIFT equ 12
  64. PAGE_MASK equ (PAGE_SIZE - 1)
  65. PTE_VALID equ 23h
  66. PDE_SHIFT equ 22
  67. PTE_SHIFT equ 12
  68. PTE_INDEX_MASK equ 3ffh
  69. ;
  70. ; Internal defines and structures
  71. ;
  72. STACK_SIZE equ 1024
  73. HbGdt struc
  74. Limit dw ?
  75. Base dd ?
  76. Pad dw ?
  77. HbGdt ends
  78. HbContextBlock struc
  79. WakeContext db processorstatelength dup (?)
  80. OldEsp dd ?
  81. PteVa dd ?
  82. TransCr3 dd ?
  83. TransPteVa dd ?
  84. WakeHiberVa dd ?
  85. Buffer dd ?
  86. MapIndex dd ?
  87. LastMapIndex dd ?
  88. FeatureFlags dd ?
  89. Gdt db size HbGdt dup (?)
  90. Stack db STACK_SIZE dup (?)
  91. BufferData db ? ; buffer starts here
  92. HbContextBlock ends
  93. ;
  94. ; Addresses based from ebp
  95. ;
  96. SourcePage equ [ebp + PAGE_SIZE * PTE_SOURCE]
  97. DestPage equ [ebp + PAGE_SIZE * PTE_DEST]
  98. Map equ [ebp + PAGE_SIZE * PTE_MAP_PAGE]
  99. Remap equ [ebp + PAGE_SIZE * PTE_REMAP_PAGE]
  100. Context equ [ebp + PAGE_SIZE * PTE_HIBER_CONTEXT].HbContextBlock
  101. _TEXT SEGMENT PARA PUBLIC 'CODE' ; Start 32 bit code
  102. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  103. ;++
  104. ;
  105. ; VOID
  106. ; WakeDispatch (
  107. ; )
  108. ;
  109. ; Routine Description:
  110. ;
  111. ; Relocatable code which copies any remap page to it's final resting
  112. ; place and then restores the processors wake context.
  113. ;
  114. ; Arguments:
  115. ;
  116. ; Return
  117. ;
  118. ; Only returns if there's an internal failure
  119. ;
  120. ;--
  121. cPublicProc _WakeDispatcher, 0
  122. public _WakeDispatcherStart
  123. _WakeDispatcherStart label dword
  124. push ebp
  125. push ebx
  126. push esi
  127. push edi
  128. ;
  129. ; Load EBP with base of hiber va. Everything will be relative from EBP
  130. ;
  131. mov ebp, _HiberVa
  132. ;
  133. ; Initialize HbContextBlock
  134. ;
  135. mov eax, _HiberFirstRemap
  136. mov ecx, _HiberLastRemap
  137. lea edx, Context.BufferData
  138. mov esi, _HiberPtes
  139. mov Context.MapIndex, eax
  140. mov Context.LastMapIndex, ecx
  141. mov Context.OldEsp, esp
  142. mov Context.Buffer, edx
  143. mov Context.PteVa, esi
  144. mov eax, _HiberPageFrames [PTE_TRANSFER_PDE * 4]
  145. mov ecx, _HiberTransVa
  146. mov edx, _HiberIdentityVa
  147. mov Context.TransCr3, eax
  148. mov Context.TransPteVa, ecx
  149. mov Context.WakeHiberVa, edx
  150. mov eax, _HiberImageFeatureFlags
  151. mov Context.FeatureFlags, eax
  152. DBGOUT 1
  153. ;
  154. ; Copy gdt to shared buffer and switch to it
  155. ;
  156. sgdt fword ptr Context.Gdt
  157. movzx ecx, Context.Gdt.Limit
  158. inc ecx
  159. push ecx
  160. call AllocateHeap
  161. pop ecx
  162. mov edi, eax
  163. mov esi, Context.Gdt.Base
  164. rep movsb
  165. mov Context.Gdt.Base, eax
  166. lgdt fword ptr Context.Gdt
  167. sub eax, ebp
  168. add eax, Context.WakeHiberVa
  169. mov Context.Gdt.Base, eax
  170. ;
  171. ; Locate hiber ptes in hibernated image. First get the PDE, then find
  172. ; the PTE for the hiber ptes.
  173. ;
  174. mov eax, dword ptr Context.WakeContext.PsSpecialRegisters.SrCr3
  175. shr eax, PAGE_SHIFT
  176. call LocatePage
  177. push eax
  178. push PTE_SOURCE
  179. call SetPte
  180. mov ecx, Context.WakeHiberVa
  181. shr ecx, PDE_SHIFT ; (ecx) = index into PDE
  182. mov eax, [eax+ecx*4] ; (eax) = PDE for WakeHiberVa PTE
  183. shr eax, PAGE_SHIFT
  184. call LocatePage
  185. push eax
  186. push PTE_SOURCE
  187. call SetPte
  188. mov ecx, Context.WakeHiberVa
  189. shr ecx, PTE_SHIFT
  190. and ecx, PTE_INDEX_MASK ; (ecx) = index into PTE
  191. lea edi, [eax+ecx*4] ; (edi) = address of WakeHiber PTEs
  192. ;
  193. ; Copy the current HiberPtes to the wake image Ptes
  194. ;
  195. mov esi, Context.PteVa
  196. mov ecx, HIBER_PTES
  197. rep movsd
  198. ;
  199. ; If break on wake, set the image header signature in destionation
  200. ;
  201. cmp _HiberBreakOnWake, 0
  202. jz short hd05
  203. mov eax, _HiberImagePageSelf
  204. call LocatePage
  205. push eax
  206. push PTE_DEST
  207. call SetPte
  208. mov dword ptr [eax], 706B7262h ; 'brkp'
  209. ;
  210. ; Switch to transition CR3
  211. ;
  212. hd05:
  213. DBGOUT 2
  214. mov ebx, Context.WakeHiberVa
  215. mov eax, Context.TransCr3
  216. shl eax, PAGE_SHIFT
  217. mov cr3, eax
  218. ;
  219. ; Move to wake images hiber va
  220. ;
  221. mov edi, ebx
  222. add ebx, PTE_DISPATCHER_START * PAGE_SIZE
  223. add ebx, offset hd10 - offset _WakeDispatcherStart
  224. jmp ebx
  225. hd10: mov ebp, edi
  226. mov eax, Context.TransPteVa
  227. mov Context.PteVa, eax
  228. lea esp, Context.Stack + STACK_SIZE
  229. lgdt fword ptr Context.Gdt
  230. ;
  231. ; Copy all pages to final locations
  232. ;
  233. DBGOUT 3
  234. mov edx, Context.MapIndex
  235. hd30: cmp edx, Context.LastMapIndex
  236. jnc short hd40
  237. push dword ptr Map.[edx*4]
  238. push PTE_SOURCE
  239. call SetPte
  240. mov esi, eax
  241. push dword ptr Remap.[edx*4]
  242. push PTE_DEST
  243. call SetPte
  244. mov edi, eax
  245. mov ecx, PAGE_SIZE / 4
  246. rep movsd
  247. inc edx
  248. jmp short hd30
  249. ;
  250. ; Restore processors wake context
  251. ;
  252. hd40: DBGOUT 5
  253. lea esi, Context.WakeContext.PsSpecialRegisters
  254. mov eax, cr3 ; issue a couple of flushes
  255. mov cr3, eax ; before enabling global ptes
  256. mov cr3, eax
  257. mov eax, [esi].SrCr4
  258. test Context.FeatureFlags, KF_CR4
  259. jz short hd50
  260. mov cr4, eax
  261. hd50: mov eax, [esi].SrCr3
  262. mov cr3, eax
  263. mov ecx, [esi].SrCr0
  264. mov cr0, ecx ; on kernel's cr0
  265. DBGOUT 6
  266. mov ecx, [esi].SrGdtr+2 ; base of GDT
  267. lgdt fword ptr [esi].SrGdtr ; load gdtr (w/matching flat cs & ds selectors)
  268. lidt fword ptr [esi].SrIdtr ; load idtr
  269. lldt word ptr [esi].SrLdtr ; load ldtr
  270. movzx eax, word ptr [esi].SrTr ; tss selector
  271. and byte ptr [eax+ecx+5], 0fdh ; clear the busy bit in the TSS
  272. ltr ax ; load tr
  273. mov ds, word ptr Context.WakeContext.PsContextFrame.CsSegDs
  274. mov es, word ptr Context.WakeContext.PsContextFrame.CsSegEs
  275. mov fs, word ptr Context.WakeContext.PsContextFrame.CsSegFs
  276. mov gs, word ptr Context.WakeContext.PsContextFrame.CsSegGs
  277. mov ss, word ptr Context.WakeContext.PsContextFrame.CsSegSs
  278. mov ebx, dword ptr Context.WakeContext.PsContextFrame.CsEbx
  279. mov ecx, dword ptr Context.WakeContext.PsContextFrame.CsEcx
  280. mov edx, dword ptr Context.WakeContext.PsContextFrame.CsEdx
  281. mov edi, dword ptr Context.WakeContext.PsContextFrame.CsEdi
  282. mov esp, dword ptr Context.WakeContext.PsContextFrame.CsEsp
  283. push dword ptr Context.WakeContext.PsContextFrame.CsEFlags
  284. movzx eax, word ptr Context.WakeContext.PsContextFrame.CsSegCs
  285. push eax
  286. push dword ptr Context.WakeContext.PsContextFrame.CsEip
  287. push dword ptr Context.WakeContext.PsContextFrame.CsEbp
  288. push dword ptr Context.WakeContext.PsContextFrame.CsEsi
  289. push dword ptr Context.WakeContext.PsContextFrame.CsEax
  290. lea esi, Context.WakeContext.PsSpecialRegisters.SrKernelDr0
  291. lodsd
  292. mov dr0, eax ; load dr0-dr7
  293. lodsd
  294. mov dr1, eax
  295. lodsd
  296. mov dr2, eax
  297. lodsd
  298. mov dr3, eax
  299. lodsd
  300. mov dr6, eax
  301. lodsd
  302. mov dr7, eax
  303. DBGOUT 7
  304. pop eax
  305. pop esi
  306. pop ebp
  307. iretd
  308. ; this exit is only used in the shared buffer overflows
  309. Abort:
  310. mov esp, Context.OldEsp
  311. pop ebp
  312. pop ebx
  313. pop esi
  314. pop edi
  315. stdRET _WakeDispatcher
  316. ;++
  317. ;
  318. ; PUCHAR
  319. ; AllocateHeap (
  320. ; IN ULONG Length passed in ECX
  321. ; )
  322. ;
  323. ; Routine Description:
  324. ;
  325. ; Allocates the specified bytes from the wake context page.
  326. ;
  327. ; N.B. This function is part of HiberDispacther.
  328. ;
  329. ; Arguments:
  330. ; ECX - Length to allocate
  331. ;
  332. ; Returns:
  333. ; EAX - Virtual address of bytes allocated
  334. ;
  335. ; Uses:
  336. ; EAX, ECX, EDX
  337. ;
  338. ;--
  339. AllocateHeap label proc
  340. mov eax, Context.Buffer
  341. mov edx, eax
  342. test eax, 01fh ; round to 32 byte boundry
  343. jz short ah20
  344. and eax, not 01fh
  345. add eax, 20h
  346. ah20: add ecx, eax
  347. mov Context.Buffer, ecx
  348. xor ecx, edx
  349. and ecx, 0ffffffffh - PAGE_MASK
  350. jnz short Abort
  351. ret
  352. ;++
  353. ;
  354. ; PUCHAR
  355. ; SetPte (
  356. ; IN ULONG PteIndex
  357. ; IN ULONG PageFrameNumber
  358. ; )
  359. ;
  360. ; Routine Description:
  361. ;
  362. ;
  363. ; N.B. This function is part of HiberDispacther.
  364. ;
  365. ; Arguments:
  366. ;
  367. ;
  368. ; Returns:
  369. ; EAX va of mapped pte
  370. ;
  371. ; Uses:
  372. ; EAX, ECX, EDX
  373. ;
  374. ;--
  375. SetPte label proc
  376. push ecx
  377. mov eax, [esp+8] ; (eax) = pte index
  378. shl eax, 2 ; * 4
  379. add eax, Context.PteVa ; + pte base
  380. mov ecx, [esp+12] ; (ecx) = page frame number
  381. shl ecx, PAGE_SHIFT
  382. or ecx, PTE_VALID
  383. mov [eax], ecx ; set the Pte
  384. mov eax, [esp+8]
  385. shl eax, PAGE_SHIFT
  386. add eax, ebp ; (eax) = va mapped by pte
  387. invlpg [eax]
  388. pop ecx
  389. ret 8
  390. ;++
  391. ;
  392. ; ULONG
  393. ; LocatePage (
  394. ; IN ULONG PageNumber passed in eax
  395. ; )
  396. ;
  397. ; Routine Description:
  398. ;
  399. ; Find the page specified by page number in the wake context.
  400. ; The pagenumber must be a valid page.
  401. ;
  402. ; N.B. This function is part of HiberDispacther.
  403. ;
  404. ; Arguments:
  405. ; EAX - Length to allocate
  406. ;
  407. ; Returns:
  408. ; EAX - Virtual address of bytes allocated
  409. ;
  410. ; Uses:
  411. ; EAX, ECX, EDX
  412. ;
  413. ;--
  414. LocatePage label proc
  415. ;
  416. ; Scan the remap entries for this page. If it's found, get the
  417. ; source address. If it's not found, then it's already at it's
  418. ; proper address
  419. ;
  420. mov edx, Context.MapIndex
  421. dec edx
  422. lp10: inc edx
  423. cmp edx, Context.LastMapIndex
  424. jnc short lp20
  425. cmp eax, Remap.[edx*4]
  426. jnz short lp10
  427. mov eax, Map.[edx*4]
  428. lp20: ret
  429. public _WakeDispatcherEnd
  430. _WakeDispatcherEnd label dword
  431. stdENDP _WakeDispatcher
  432. _TEXT ends
  433. end