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.

823 lines
27 KiB

  1. ;++
  2. ;
  3. ;Copyright (c) 1997-2002 Microsoft Corporation
  4. ;
  5. ;Module Name:
  6. ;
  7. ; wake64.asm
  8. ;
  9. ;Abstract:
  10. ;
  11. ; This module contains relocatable code to perform tasks necessary
  12. ; at the final stage of waking process on Amd64.
  13. ;
  14. ;Author:
  15. ;
  16. ; Ken Reneris (kenr) 05-May-1997
  17. ;
  18. ;Revision History:
  19. ;
  20. ; Steve Deng (sdeng) 27-Aug-2002
  21. ; Initial Amd64 version
  22. ;
  23. ;--
  24. .586p
  25. .xlist
  26. include ksamd64.inc
  27. include callconv.inc
  28. .list
  29. extrn _HiberPtes:DWORD
  30. extrn _HiberVa:DWORD
  31. extrn _HiberFirstRemap:DWORD
  32. extrn _HiberLastRemap:DWORD
  33. extrn _HiberPageFrames:DWORD
  34. extrn _HiberTransVaAmd64:QWORD
  35. extrn _HiberIdentityVaAmd64:QWORD
  36. extrn _HiberImageFeatureFlags:DWORD
  37. extrn _HiberBreakOnWake:BYTE
  38. extrn _HiberImagePageSelf:DWORD
  39. extrn _HiberNoHiberPtes:DWORD
  40. extrn _HiberNoExecute:DWORD
  41. extrn _BlAmd64TopLevelPte:DWORD
  42. extrn _HiberInProgress:DWORD
  43. extrn _BlAmd64GdtSize:DWORD
  44. EXTRNP _BlAmd64SwitchToLongMode,0
  45. EXTRNP _BlAmd64BuildAmd64GDT,2
  46. ;
  47. ; These equates define the usuage of reserved hiber PTEs. They must match
  48. ; the definitions in bldr.h
  49. ;
  50. PTE_SOURCE equ 0
  51. PTE_DEST equ 1
  52. PTE_MAP_PAGE equ 2
  53. PTE_REMAP_PAGE equ 3
  54. PTE_HIBER_CONTEXT equ 4
  55. PTE_TRANSFER_PDE equ 5
  56. PTE_WAKE_PTE equ 6
  57. PTE_DISPATCHER_START equ 7
  58. ;
  59. ; Processor paging defines
  60. ;
  61. PAGE_SIZE equ 4096
  62. PAGE_MASK equ (PAGE_SIZE - 1)
  63. PAGE_SHIFT equ 12
  64. PTE_VALID equ 23h
  65. PTI_MASK_AMD64 equ 1ffh
  66. PDI_MASK_AMD64 equ 1ffh
  67. PPI_MASK_AMD64 equ 1ffh
  68. PXI_MASK_AMD64 equ 1ffh
  69. PTI_SHIFT_AMD64 equ 12
  70. PDI_SHIFT_AMD64 equ 21
  71. PPI_SHIFT_AMD64 equ 30
  72. PXI_SHIFT_AMD64 equ 39
  73. ;
  74. ; Part of the code in this module runs in 64-bit mode. But everything
  75. ; is compiled by 32-bit compiler. The equates and macros defined here are
  76. ; used to indicate the actual behavior of the intructions in 64-bit mode.
  77. ;
  78. rax equ eax
  79. rcx equ ecx
  80. rdx equ edx
  81. rbx equ ebx
  82. rsp equ esp
  83. rbp equ ebp
  84. rsi equ esi
  85. rdi equ edi
  86. r8 equ eax
  87. r9 equ ecx
  88. r10 equ edx
  89. r11 equ ebx
  90. r12 equ esp
  91. r13 equ ebp
  92. r14 equ esi
  93. r15 equ edi
  94. PREFIX64 macro
  95. db 048h
  96. endm
  97. MOV64 macro a, b
  98. PREFIX64
  99. mov dword ptr a, dword ptr b
  100. endm
  101. LEA64 macro a, b
  102. PREFIX64
  103. lea a, b
  104. endm
  105. SHL64 macro a, b
  106. PREFIX64
  107. shl a, b
  108. endm
  109. ADD64 macro a, b
  110. PREFIX64
  111. add a, b
  112. endm
  113. RETF64 macro a, b
  114. PREFIX64
  115. retf
  116. endm
  117. IRET64 macro a, b
  118. PREFIX64
  119. iretd
  120. endm
  121. LDRX64 macro a, b
  122. db 04ch
  123. mov a, dword ptr b
  124. endm
  125. LDCR8 macro a
  126. db 44h
  127. mov cr0, a
  128. endm
  129. ;
  130. ; Private data structures
  131. ;
  132. STACK_SIZE equ 1024
  133. HbGdt struc
  134. Limit dw 0
  135. Base dd 0
  136. BaseHigh dd 0
  137. Pad dw 0
  138. HbGdt ends
  139. HbContextBlock struc
  140. ProcessorState db processorstatelength dup (?)
  141. OldEsp dd ?
  142. PteVa dd ?
  143. pteVaHigh dd ?
  144. TransCr3 dd ?
  145. TransPteVa dd ?
  146. TransPteVaHigh dd ?
  147. WakeHiberVa dd ?
  148. WakeHiberVaHigh dd ?
  149. Buffer dd ?
  150. MapIndex dd ?
  151. LastMapIndex dd ?
  152. FeatureFlags dd ?
  153. NoExecute dd ?
  154. Gdt32 db size HbGdt dup (0)
  155. Gdt64 db size HbGdt dup (0)
  156. Stack db STACK_SIZE dup (?)
  157. BufferData db ?
  158. HbContextBlock ends
  159. ;
  160. ; Addresses based from ebp
  161. ;
  162. SourcePage equ [ebp + PAGE_SIZE * PTE_SOURCE]
  163. DestPage equ [ebp + PAGE_SIZE * PTE_DEST]
  164. Map equ [ebp + PAGE_SIZE * PTE_MAP_PAGE]
  165. Remap equ [ebp + PAGE_SIZE * PTE_REMAP_PAGE]
  166. Context equ [ebp + PAGE_SIZE * PTE_HIBER_CONTEXT].HbContextBlock
  167. ContextFrame equ Context.ProcessorState.PsContextFrame
  168. SpecialRegisters equ Context.ProcessorState.PsSpecialRegisters
  169. _TEXT SEGMENT PARA PUBLIC 'CODE'
  170. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  171. ;++
  172. ;
  173. ; VOID
  174. ; WakeDispatcherAmd64 (
  175. ; )
  176. ;
  177. ; Routine Description:
  178. ;
  179. ; Relocatable code which copies any remap page to it's final resting
  180. ; place and then restores the processors wake context.
  181. ;
  182. ; Arguments:
  183. ;
  184. ; None
  185. ;
  186. ; Return
  187. ;
  188. ; Only returns if there's an internal failure
  189. ;
  190. ;--
  191. cPublicProc _WakeDispatcherAmd64, 0
  192. public _WakeDispatcherAmd64Start
  193. _WakeDispatcherAmd64Start label dword
  194. ;
  195. ; Save nonvolatile registers on stack. The saved values are
  196. ; only used when wake process failed.
  197. ;
  198. push ebp
  199. push ebx
  200. push esi
  201. push edi
  202. ;
  203. ; Load ebp with base of hiber va. Everything will be relative
  204. ; from ebp
  205. ;
  206. mov ebp, _HiberVa
  207. mov Context.OldEsp, esp ; save esp value in case of failure
  208. ;
  209. ; Make a private copy of the data we need to HbContextBlock.
  210. ; We'll not have access to these globals after switching to
  211. ; long mode.
  212. ;
  213. lea edx, Context.BufferData
  214. mov eax, _HiberFirstRemap
  215. mov ecx, _HiberLastRemap
  216. mov esi, _HiberPtes
  217. mov Context.MapIndex, eax
  218. mov Context.LastMapIndex, ecx
  219. mov Context.Buffer, edx
  220. mov Context.PteVa, esi
  221. mov eax, _HiberPageFrames [PTE_TRANSFER_PDE * 4]
  222. mov edx, dword ptr _HiberIdentityVaAmd64
  223. mov esi, dword ptr _HiberIdentityVaAmd64 + 4
  224. mov Context.TransCr3, eax
  225. mov Context.WakeHiberVa, edx
  226. mov Context.WakeHiberVaHigh, esi
  227. mov eax, _HiberImageFeatureFlags
  228. mov ecx, _HiberNoExecute
  229. mov edx, dword ptr _HiberTransVaAmd64
  230. mov esi, dword ptr _HiberTransVaAmd64+4
  231. mov Context.FeatureFlags, eax
  232. mov Context.NoExecute, ecx
  233. mov Context.TransPteVa, edx
  234. mov Context.TransPteVaHigh, esi
  235. ;
  236. ; Copy current GDT to private buffer
  237. ;
  238. sgdt fword ptr Context.Gdt32 ; save current GDTR
  239. movzx ecx, Context.Gdt32.Limit; ecx = GDT limit
  240. inc ecx ; ecx = size to allocate
  241. push ecx ; save size value on stack
  242. call AllocateHeap ; allocate a buffer for GDT table
  243. pop ecx ; restore GDT size to ecx
  244. mov edi, eax ; edi = address of allocated buffer
  245. mov esi, Context.Gdt32.Base ; esi = address of current GDT table
  246. rep movsb ; copy GDT to allocated buffer
  247. mov Context.Gdt32.Base, eax ; set GDT new base
  248. ;
  249. ; Build 64-bit Global Descriptor Table
  250. ;
  251. mov ecx, _BlAmd64GdtSize ; specify allocate size in ecx
  252. call AllocateHeap ; allocate a buffer for 64-bit GDT
  253. push eax ; eax has base of alloctated buffer
  254. mov Context.Gdt64.Base, eax ; set the base of 64-bit GDT
  255. mov ax, word ptr _BlAmd64GdtSize
  256. mov Context.Gdt64.Limit, ax ; set the limit of 64-bit GDT
  257. push 0 ; specify SysTss = 0 for the call below
  258. mov ebx, _BlAmd64BuildAmd64GDT@8
  259. call dword ptr ebx ; build 64-bit GDT in allocated buffer
  260. ;
  261. ; Now we'll locate hiber ptes in hiber image and set them to the
  262. ; values of current HiberPtes
  263. ;
  264. mov eax, dword ptr SpecialRegisters.PsCr3
  265. shr eax, PAGE_SHIFT ; eax = page number of PML4 table
  266. call LocatePage ; locate the page described by eax
  267. push eax ; eax has the pfn of the page located
  268. push PTE_SOURCE ; specify which PTE to use
  269. call SetPteX86 ; map the located page
  270. ;
  271. ; Locate the PDPT page and map it
  272. ;
  273. mov ecx, Context.WakeHiberVaHigh
  274. shr ecx, PXI_SHIFT_AMD64 - 32
  275. and ecx, PXI_MASK_AMD64 ; ecx = PML4E index of WakeHiberVa
  276. mov eax, [eax+ecx*8] ; get PML4E entry
  277. shr eax, PAGE_SHIFT ; eax = page frame number of PDPT
  278. call LocatePage ; locate the page described by eax
  279. push eax ; eax has the pfn of the page located
  280. push PTE_SOURCE ; specify which PTE to use
  281. call SetPteX86 ; map the located page
  282. ;
  283. ; Locate the PDE page and map it
  284. ;
  285. mov ecx, Context.WakeHiberVa;
  286. mov edx, Context.WakeHiberVaHigh
  287. shrd ecx, edx, PPI_SHIFT_AMD64 ; shift right to PPI part
  288. and ecx, PPI_MASK_AMD64 ; ecx = PDPT index of WakeHiberVa
  289. mov eax, [eax+ecx*8] ; get PDPT entry
  290. shr eax, PAGE_SHIFT ; eax = page frame number of PDE
  291. call LocatePage ; locate the page described by eax
  292. push eax ; eax has the pfn of the page located
  293. push PTE_SOURCE ; specify which PTE to use
  294. call SetPteX86 ; map the located page
  295. ;
  296. ; Locate the PTE page and map it
  297. ;
  298. mov ecx, Context.WakeHiberVa;
  299. shr ecx, PDI_SHIFT_AMD64 ; shift right to PDE part
  300. and ecx, PDI_MASK_AMD64 ; ecx = PDE index
  301. mov eax, [eax+ecx*8] ; get PDE entry
  302. shr eax, PAGE_SHIFT ; eax = page frame number of PTE
  303. call LocatePage ; locate the page described by eax
  304. push eax ; eax has the pfn of the page located
  305. push PTE_SOURCE ; specify which PTE to use
  306. call SetPteX86 ; map the located page
  307. ;
  308. ; Calculate the address of wake image hiber ptes
  309. ;
  310. mov ecx, Context.WakeHiberVa;
  311. shr ecx, PTI_SHIFT_AMD64 ; shift right to PTE part
  312. and ecx, PTI_MASK_AMD64 ; ecx = PTE index
  313. lea edi, [eax+ecx*8] ; edi = address of wake hiber PTEs
  314. ;
  315. ; Copy current HiberPtes to the wake image Ptes
  316. ;
  317. xor eax, eax ; set eax to 0 for stosd below
  318. mov esi, Context.PteVa ; current HiberPte address
  319. mov ecx, _HiberNoHiberPtes ; Number of PTEs to copy
  320. @@: movsd ; translate 32-bit PTE to 64-bit PTE
  321. stosd ; Assume the high dword of 64-bit
  322. dec ecx ; pte is zero. Otherwise hibernation
  323. jnz short @b ; should be disabled
  324. ;
  325. ; If break on wake, set the image header signature in destionation
  326. ;
  327. cmp _HiberBreakOnWake, 0
  328. jz short @f ; skip this step if flag is not set
  329. mov eax, _HiberImagePageSelf; eax = page number of image header
  330. call LocatePage ; locate the page described by eax
  331. push eax ; eax has the pfn of the page located
  332. push PTE_DEST ; specify which PTE to use
  333. call SetPteX86 ; map the located page
  334. mov [eax], 706B7262h ; set signature to 'brkp'
  335. ;
  336. ; Switch to long mode
  337. ;
  338. @@: lgdt fword ptr Context.Gdt32 ; switch GDT to the one in our buffer
  339. lea esp, Context.Stack + STACK_SIZE ; move stack to safe place
  340. and esp, 0fffffff8h ; align to 16 byte boundary
  341. mov eax, Context.TransCr3 ; eax = pfn of transition CR3
  342. shl eax, PAGE_SHIFT ; eax = transition CR3
  343. mov [_BlAmd64TopLevelPte], eax ; initialize these two globals
  344. mov [_HiberInProgress], 1 ; for use in BlAmd64SwitchToLongMode
  345. mov eax, _BlAmd64SwitchToLongMode@0
  346. call dword ptr eax ; switch to long mode
  347. ;
  348. ; Now we are in 32-bit compatible mode.
  349. ;
  350. mov ebx, ebp ; ebx = Hiberva
  351. add ebx, PTE_DISPATCHER_START * PAGE_SIZE ; add dispatch code address
  352. add ebx, in_64bit_mode - _WakeDispatcherAmd64Start ; ebx = Hiberva
  353. ; relative new IP
  354. push word ptr KGDT64_R0_CODE ; push code selector
  355. push ebx ; push new IP address
  356. lgdt fword ptr Context.Gdt64 ; load 64-bit GDTR
  357. retf ; jump to next instruction and reload cs
  358. in_64bit_mode:
  359. ;
  360. ; At this point we are in 64 bit mode.
  361. ; We now move everything to WakeHiberVa relative address.
  362. ;
  363. mov eax, Context.Gdt64.Base ; get HiberVa relative GDT base
  364. sub eax, ebp ; eax = offset of GDT base to HiberVa
  365. ADD64 rax, Context.WakeHiberVa; rax = WakeHiberVa relative GDT base
  366. MOV64 Context.Gdt64.Base, rax ; set GDT base
  367. MOV64 rbx, Context.WakeHiberVa; get WakeHiberVa
  368. MOV64 rbp, rbx ; switch rbp from HiberVa to WakeHiberVa
  369. MOV64 rax, Context.TransPteVa ; rax = HiberTransVaAmd64
  370. MOV64 Context.PteVa, rax ; Pteva = pte address of WakeHiberVa
  371. LEA64 rsp, Context.Stack+STACK_SIZE ; move stack to safe place
  372. ADD64 rbx, PTE_DISPATCHER_START*PAGE_SIZE ; rbx = dispatch code base
  373. ADD64 rbx, wd10-_WakeDispatcherAmd64Start ; rbx = WakeHiberVa rela-
  374. ; tive address of "wd10"
  375. lgdt fword ptr Context.Gdt64 ; switch to WakeHiberVa relative GDT
  376. push dword ptr KGDT64_R0_CODE; code selector
  377. push rbx ; rip address
  378. RETF64 ; jump to WakeHiberVa relative code address
  379. ;
  380. ; Copy all pages to final locations
  381. ;
  382. wd10: mov ebx, Context.MapIndex ; get initial map index
  383. wd20: cmp ebx, Context.LastMapIndex ; check if any pages left
  384. jnc short wd30 ; we are done!
  385. mov edx, Map.[ebx*4] ; edx = page number to be copied
  386. mov ecx, PTE_SOURCE ; use hiber pte PTE_SOURCE
  387. call SetPteAmd64 ; map the source page
  388. MOV64 rsi, rax ; rsi = address of source page
  389. mov edx, Remap.[ebx*4] ; edx = dest page number
  390. mov ecx, PTE_DEST ; use hiber pte PTE_DEST
  391. call SetPteAmd64 ; map the dest page
  392. MOV64 rdi, rax ; rdi = address of dest page
  393. mov ecx, PAGE_SIZE / 4 ; set copy size to one page
  394. rep movsd ; coping ...
  395. add ebx, 1 ; increment ebx to next index
  396. jmp short wd20 ;
  397. ;
  398. ; Restore processors wake context
  399. ;
  400. wd30: LEA64 rsi, SpecialRegisters ; rsi = base of special registers
  401. MOV64 rax, cr3 ; flush before enabling kernel paging
  402. MOV64 cr3, rax ;
  403. MOV64 rax, [rsi].PsCr4 ; get saved CR4
  404. MOV64 cr4, rax ; restore CR4
  405. MOV64 rax, [rsi].PsCr3 ; get saved CR3
  406. MOV64 cr3, rax ; restore CR3
  407. MOV64 rcx, [rsi].PsCr0 ; get saved CR0
  408. MOV64 cr0, rcx ; restore CR0
  409. ;
  410. ; On kernel's paging now
  411. ;
  412. MOV64 rax, [rsi].PsCr8 ; get saved CR8
  413. LDCR8 rax ; restore CR8
  414. lgdt fword ptr [rsi].PsGdtr ; restore GDTR
  415. lidt fword ptr [rsi].PsIdtr ; restore IDTR
  416. lldt word ptr [rsi].PsLdtr ; restore LDTR
  417. mov ds, word ptr ContextFrame.CxSegDs ; restore segment registers
  418. mov es, word ptr ContextFrame.CxSegEs ;
  419. mov ss, word ptr ContextFrame.CxSegSs ;
  420. mov fs, word ptr ContextFrame.CxSegFs ;
  421. mov gs, word ptr ContextFrame.CxSegGs ;
  422. MOV64 rcx, [rsi].PsGdtr+2 ; rcx = base of kernel GDT
  423. movzx eax, word ptr [rsi].PsTr; TSS selector
  424. and byte ptr [rax+rcx+5], NOT 2; clear busy bit in the TSS
  425. ltr word ptr [rsi].PsTr ; restore TR
  426. mov ecx, MSR_GS_BASE ; restore MSRs
  427. mov eax, [rsi].SrMsrGsBase ;
  428. mov edx, [rsi].SrMsrGsBase + 4
  429. wrmsr ;
  430. mov ecx, MSR_GS_SWAP ;
  431. mov eax, [rsi].SrMsrGsSwap ;
  432. mov edx, [rsi].SrMsrGsSwap + 4
  433. wrmsr ;
  434. mov ecx, MSR_STAR ;
  435. mov eax, [rsi].SrMsrStar ;
  436. mov edx, [rsi].SrMsrStar + 4;
  437. wrmsr ;
  438. mov ecx, MSR_LSTAR ;
  439. mov eax, [rsi].SrMsrLStar ;
  440. mov edx, [rsi].SrMsrLStar + 4
  441. wrmsr
  442. mov ecx, MSR_CSTAR ;
  443. mov eax, [rsi].SrMsrCStar ;
  444. mov edx, [rsi].SrMsrCStar + 4
  445. wrmsr ;
  446. mov ecx, MSR_SYSCALL_MASK ;
  447. mov eax, [rsi].SrMsrSyscallMask
  448. mov edx, [rsi].SrMsrSyscallMask + 4
  449. wrmsr ;
  450. ;
  451. ; No-execute should be enabled while switching to long mode.
  452. ; If this option was disabled in OS, we should disable it here.
  453. ;
  454. cmp Context.NoExecute, 0 ; check no-execute bit
  455. jnz short wd40 ; if it is enabled, do nothing
  456. mov ecx, MSR_EFER ; ecx = EFER address
  457. rdmsr ; read current value of EFER
  458. and eax, NOT 800h ; clear NXE bit of EFER
  459. wrmsr ; write EFER
  460. wd40: MOV64 rbx, ContextFrame.CxRbx ; restore general purpose registers
  461. MOV64 rcx, ContextFrame.CxRcx ;
  462. MOV64 rdx, ContextFrame.CxRdx ;
  463. MOV64 rdi, ContextFrame.CxRdi ;
  464. LDRX64 r8, ContextFrame.CxR8 ;
  465. LDRX64 r9, ContextFrame.CxR9 ;
  466. LDRX64 r10, ContextFrame.CxR10 ;
  467. LDRX64 r11, ContextFrame.CxR11 ;
  468. LDRX64 r12, ContextFrame.CxR12 ;
  469. LDRX64 r13, ContextFrame.CxR13 ;
  470. LDRX64 r14, ContextFrame.CxR14 ;
  471. LDRX64 r15, ContextFrame.CxR15 ;
  472. xor eax, eax ; restore debug registers
  473. mov dr7, rax ;
  474. MOV64 rax, [esi].PsKernelDr0 ;
  475. mov dr0, rax ;
  476. MOV64 rax, [esi].PsKernelDr1 ;
  477. mov dr1, rax ;
  478. MOV64 rax, [esi].PsKernelDr2 ;
  479. mov dr2, rax ;
  480. MOV64 rax, [esi].PsKernelDr3 ;
  481. mov dr3, rax ;
  482. xor eax, eax ;
  483. mov dr6, rax ;
  484. MOV64 rax, [esi].PsKernelDr7 ;
  485. mov dr7, rax ;
  486. ;
  487. ; Prepare stack content for the iret.
  488. ; N.B. Every "push" below stores a qword on stack in 64-bit mode.
  489. ;
  490. movzx eax, word ptr ContextFrame.CxSegSs
  491. push rax
  492. push dword ptr ContextFrame.CxRsp
  493. push dword ptr ContextFrame.CxEFlags
  494. movzx eax, word ptr ContextFrame.CxSegCs
  495. push rax
  496. push dword ptr ContextFrame.CxRip
  497. ;
  498. ; Restore the last few registers
  499. ;
  500. push dword ptr ContextFrame.CxRbp
  501. push dword ptr ContextFrame.CxRsi
  502. push dword ptr ContextFrame.CxRax
  503. pop rax
  504. pop rsi
  505. pop rbp
  506. ;
  507. ; Pass control to kernel
  508. ;
  509. IRET64
  510. ;
  511. ; This exit is only used in the shared buffer overflows
  512. ;
  513. Abort: mov esp, Context.OldEsp
  514. pop edi
  515. pop esi
  516. pop ebx
  517. pop ebp
  518. stdRET _WakeDispatcherAmd64
  519. ;++
  520. ;
  521. ; PUCHAR
  522. ; AllocateHeap (
  523. ; IN ULONG Length
  524. ; )
  525. ;
  526. ; Routine Description:
  527. ;
  528. ; Allocates the specified bytes from the wake context page.
  529. ;
  530. ; This function runs in legacy 32-bit mode.
  531. ;
  532. ; N.B. This function is part of WakeDispatcher.
  533. ;
  534. ; Arguments:
  535. ;
  536. ; ECX - Length to allocate
  537. ;
  538. ; Returns:
  539. ;
  540. ; EAX - Virtual address of bytes allocated
  541. ;
  542. ; Register modified:
  543. ;
  544. ; EAX, ECX, EDX
  545. ;
  546. ;--
  547. AllocateHeap label proc
  548. mov eax, Context.Buffer ; eax = base address of free memory
  549. mov edx, eax ;
  550. test eax, 01fh ; check if it is at 32 byte boundary
  551. jz short ah20 ; if yes, do nothing
  552. and eax, not 01fh ;
  553. add eax, 20h ; round to next 32 byte boundary
  554. ah20: add ecx, eax ; ecx = base address + allocate length
  555. mov Context.Buffer, ecx ; update ase address of free memory
  556. xor ecx, edx ;
  557. and ecx, 0ffffffffh - PAGE_MASK
  558. jnz short Abort ; abort wake process if allocation fail
  559. ret ; return on success
  560. ;++
  561. ;
  562. ; PUCHAR
  563. ; SetPteX86 (
  564. ; IN ULONG PteIndex
  565. ; IN ULONG PageFrameNumber
  566. ; )
  567. ;
  568. ; Routine Description:
  569. ;
  570. ; This function create a legacy 32-bit mapping with one of the hiber PTEs.
  571. ;
  572. ; This function runs in legacy 32-bit mode.
  573. ;
  574. ; N.B. This function is part of WakeDispatcher.
  575. ;
  576. ; Arguments:
  577. ;
  578. ; PteIndex - Specify a PTE in HiberPtes list
  579. ;
  580. ; PageFrameNumber - the page frame number of the page to be mapped
  581. ;
  582. ; Returns:
  583. ;
  584. ; EAX - va of mapped pte
  585. ;
  586. ; Registers modified:
  587. ;
  588. ; EAX
  589. ;
  590. ;--
  591. SetPteX86 label proc
  592. push ecx ; save ecx
  593. ;
  594. ; Calculate the address of the given PTE
  595. ;
  596. mov eax, [esp+8] ; eax = pte index
  597. shl eax, 2 ; times the size of PTE
  598. add eax, Context.PteVa ; add pte base address
  599. ;
  600. ; Initialize the PTE entry to the given page
  601. ;
  602. mov ecx, [esp+12] ; ecx = page frame number
  603. shl ecx, PAGE_SHIFT ;
  604. or ecx, PTE_VALID ; make a valid PTE entry
  605. mov [eax], ecx ; set the PTE
  606. ;
  607. ; Calcuate the virtual address and flush its TLB
  608. ;
  609. mov eax, [esp+8] ; eax = pte index
  610. shl eax, PAGE_SHIFT ;
  611. add eax, ebp ; eax = va mapped by pte
  612. invlpg [eax] ;
  613. pop ecx ; restore ecx
  614. ret 8
  615. ;
  616. ; PUCHAR
  617. ; SetPteAmd64 (
  618. ; IN ULONG PteIndex
  619. ; IN ULONG PageFrameNumber
  620. ; )
  621. ;
  622. ; Routine Description:
  623. ;
  624. ; This function maps a page into 4-level Amd64 mapping structure with one
  625. ; of the hiber PTEs.
  626. ;
  627. ; This function runs in long mode.
  628. ;
  629. ; N.B. This function is part of WakeDispatcher.
  630. ;
  631. ; Arguments:
  632. ;
  633. ; ECX - Specify a PTE in HiberPtes list
  634. ;
  635. ; EDX - the page frame number of the page to be mapped
  636. ;
  637. ; Returns:
  638. ;
  639. ; EAX - va of mapped pte
  640. ;
  641. ; Register modified:
  642. ;
  643. ; EAX, EDX
  644. ;
  645. ;--
  646. SetPteAmd64 label proc
  647. ;
  648. ; Calculate the address of given PTE
  649. ;
  650. mov eax, ecx ; eax = pte index
  651. shl eax, 3 ; eax = eax * 8
  652. ADD64 rax, Context.PteVa ; add pte base address
  653. ;
  654. ; Initialize the PTE entry
  655. ;
  656. SHL64 rdx, PAGE_SHIFT ;
  657. or edx, PTE_VALID ; make it a valid pte entry
  658. MOV64 [rax], rdx ; set the 64-bit Pte
  659. ;
  660. ; Calcuate the virtual address and flush its TLB
  661. ;
  662. mov eax, ecx ; eax = pte index
  663. SHL64 rax, PAGE_SHIFT ;
  664. ADD64 rax, rbp ; eax = va mapped by pte
  665. invlpg [eax] ; flush TLB of this va
  666. ret
  667. ;++
  668. ;
  669. ; ULONG
  670. ; LocatePage (
  671. ; IN ULONG PageNumber
  672. ; )
  673. ;
  674. ; Routine Description:
  675. ;
  676. ; Find the page specified by PageNumber in the wake context.
  677. ; The page number must be a valid page.
  678. ;
  679. ; This function works in 32-bit legacy mode.
  680. ;
  681. ; N.B. This function is part of WakeDispatcher.
  682. ;
  683. ; Arguments:
  684. ;
  685. ; EAX - Page frame number of the page we try to locate.
  686. ;
  687. ; Returns:
  688. ;
  689. ; EAX - Page frame number of the page which is holding the content
  690. ; of the page of interest. This number could be different from
  691. ; the page number passed in if the requested page is in the
  692. ; remap list.
  693. ;
  694. ; Uses:
  695. ;
  696. ; EAX, EDX
  697. ;
  698. ;--
  699. LocatePage label proc
  700. ;
  701. ; Scan the remap entries for this page. If it's found, get the
  702. ; source address. If it's not found, then it's already at it's
  703. ; proper address
  704. ;
  705. mov edx, Context.MapIndex ; edx = initial index
  706. dec edx ;
  707. lp10: inc edx ;
  708. cmp edx, Context.LastMapIndex ; check if we've searched to the end
  709. jnc short lp20 ; if yes, return
  710. cmp eax, Remap.[edx*4] ; is this the page we try to locate ?
  711. jnz short lp10 ; if not, try next one
  712. mov eax, Map.[edx*4] ; we found our page, retrun its clone
  713. lp20: ret
  714. public _WakeDispatcherAmd64End
  715. _WakeDispatcherAmd64End label dword
  716. stdENDP _WakeDispatcherAmd64
  717. _TEXT ends