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.

264 lines
5.2 KiB

  1. /*++
  2. Copyright (c) 1990, 1991 Microsoft Corporation
  3. Module Name:
  4. wake.c
  5. Abstract:
  6. Author:
  7. Ken Reneris
  8. Environment:
  9. Kernel Mode
  10. Revision History:
  11. --*/
  12. #include "arccodes.h"
  13. #include "bootx86.h"
  14. extern PHARDWARE_PTE PDE;
  15. extern PHARDWARE_PTE HalPT;
  16. extern ULONG HiberNoMappings;
  17. extern BOOLEAN HiberIoError;
  18. extern ULONG HiberLastRemap;
  19. extern BOOLEAN HiberOutOfRemap;
  20. PVOID HiberTransVa;
  21. ULONG HiberCurrentMapIndex;
  22. #define PDE_SHIFT 22
  23. #define PTE_SHIFT 12
  24. #define PTE_INDEX_MASK 0x3ff
  25. PVOID
  26. HbMapPte (
  27. IN ULONG PteToMap,
  28. IN ULONG Page
  29. )
  30. {
  31. PVOID Va;
  32. Va = (PVOID) (HiberVa + (PteToMap << PAGE_SHIFT));
  33. HbSetPte (Va, HiberPtes, PteToMap, Page);
  34. return Va;
  35. }
  36. PVOID
  37. HbNextSharedPage (
  38. IN ULONG PteToMap,
  39. IN ULONG RealPage
  40. )
  41. /*++
  42. Routine Description:
  43. Allocates the next available page in the free and
  44. maps the Hiber pte to the page. The allocated page
  45. is put onto the remap list
  46. Arguments:
  47. PteToMap - Which Hiber PTE to map
  48. RealPage - The page to enter into the remap table for
  49. this allocation
  50. Return Value:
  51. Virtual address of the mapping
  52. --*/
  53. {
  54. PULONG MapPage;
  55. PULONG RemapPage;
  56. ULONG DestPage;
  57. ULONG i;
  58. MapPage = (PULONG) (HiberVa + (PTE_MAP_PAGE << PAGE_SHIFT));
  59. RemapPage = (PULONG) (HiberVa + (PTE_REMAP_PAGE << PAGE_SHIFT));
  60. //
  61. // Loop until we find a free page which is not in
  62. // use by the loader image, then map it
  63. //
  64. while (HiberCurrentMapIndex < HiberNoMappings) {
  65. DestPage = MapPage[HiberCurrentMapIndex];
  66. HiberCurrentMapIndex += 1;
  67. i = HbPageDisposition (DestPage);
  68. if (i == HbPageInvalid) {
  69. HiberIoError = TRUE;
  70. return HiberBuffer;
  71. }
  72. if (i == HbPageNotInUse) {
  73. MapPage[HiberLastRemap] = DestPage;
  74. RemapPage[HiberLastRemap] = RealPage;
  75. HiberLastRemap += 1;
  76. HiberPageFrames[PteToMap] = DestPage;
  77. return HbMapPte(PteToMap, DestPage);
  78. }
  79. }
  80. HiberOutOfRemap = TRUE;
  81. return HiberBuffer;
  82. }
  83. VOID
  84. HbAllocatePtes (
  85. IN ULONG NumberPages,
  86. OUT PVOID *PteAddress,
  87. OUT PVOID *MappedAddress
  88. )
  89. /*++
  90. Routine Description:
  91. Allocated a consecutive chuck of Ptes.
  92. Arguments:
  93. NumberPage - Number of ptes to allocate
  94. PteAddress - Pointer to the first PTE
  95. MappedAddress - Base VA of the address mapped
  96. --*/
  97. {
  98. ULONG i;
  99. ULONG j;
  100. //
  101. // We use the HAL's PDE for mapping. Find enough free PTEs
  102. //
  103. for (i=0; i<=1024-NumberPages; i++) {
  104. for (j=0; j < NumberPages; j++) {
  105. if ((((PULONG)HalPT))[i+j]) {
  106. break;
  107. }
  108. }
  109. if (j == NumberPages) {
  110. *PteAddress = (PVOID) &HalPT[i];
  111. *MappedAddress = (PVOID) (0xffc00000 | (i<<12));
  112. return ;
  113. }
  114. }
  115. BlPrint("NoMem");
  116. while (1);
  117. }
  118. VOID
  119. HbSetPte (
  120. IN PVOID Va,
  121. IN PHARDWARE_PTE Pte,
  122. IN ULONG Index,
  123. IN ULONG PageNumber
  124. )
  125. /*++
  126. Routine Description:
  127. Sets the Pte to the corresponding page address
  128. --*/
  129. {
  130. Pte[Index].PageFrameNumber = PageNumber;
  131. Pte[Index].Valid = 1;
  132. Pte[Index].Write = 1;
  133. Pte[Index].WriteThrough = 0;
  134. Pte[Index].CacheDisable = 0;
  135. _asm {
  136. mov eax, Va
  137. invlpg [eax]
  138. }
  139. }
  140. VOID
  141. HiberSetupForWakeDispatch (
  142. VOID
  143. )
  144. {
  145. PHARDWARE_PTE HbPde;
  146. PHARDWARE_PTE HbPte;
  147. PHARDWARE_PTE WakePte;
  148. PHARDWARE_PTE TransVa;
  149. ULONG TransPde;
  150. ULONG WakePde;
  151. ULONG PteEntry;
  152. //
  153. // Allocate a transistion CR3. A page directory and table which
  154. // contains the hibernation PTEs
  155. //
  156. HbPde = HbNextSharedPage(PTE_TRANSFER_PDE, 0);
  157. HbPte = HbNextSharedPage(PTE_WAKE_PTE, 0); // TRANSFER_PTE, 0);
  158. RtlZeroMemory (HbPde, PAGE_SIZE);
  159. RtlZeroMemory (HbPte, PAGE_SIZE);
  160. //
  161. // Set PDE to point to PTE
  162. //
  163. TransPde = ((ULONG) HiberVa) >> PDE_SHIFT;
  164. HbPde[TransPde].PageFrameNumber = HiberPageFrames[PTE_WAKE_PTE];
  165. HbPde[TransPde].Write = 1;
  166. HbPde[TransPde].Valid = 1;
  167. //
  168. // Fill in the hiber PTEs
  169. //
  170. PteEntry = (((ULONG) HiberVa) >> PTE_SHIFT) & PTE_INDEX_MASK;
  171. TransVa = &HbPte[PteEntry];
  172. RtlCopyMemory (TransVa, HiberPtes, HIBER_PTES * sizeof(HARDWARE_PTE));
  173. //
  174. // Make another copy at the Va of the wake image hiber ptes
  175. //
  176. WakePte = HbPte;
  177. WakePde = ((ULONG) HiberIdentityVa) >> PDE_SHIFT;
  178. if (WakePde != TransPde) {
  179. WakePte = HbNextSharedPage(PTE_WAKE_PTE, 0);
  180. HbPde[WakePde].PageFrameNumber = HiberPageFrames[PTE_WAKE_PTE];
  181. HbPde[WakePde].Write = 1;
  182. HbPde[WakePde].Valid = 1;
  183. }
  184. PteEntry = (((ULONG) HiberIdentityVa) >> PTE_SHIFT) & PTE_INDEX_MASK;
  185. TransVa = &WakePte[PteEntry];
  186. RtlCopyMemory (TransVa, HiberPtes, HIBER_PTES * sizeof(HARDWARE_PTE));
  187. //
  188. // Set TransVa to be relative to the va of the transfer Cr3
  189. //
  190. HiberTransVa = (PVOID) (((PUCHAR) TransVa) - HiberVa + (PUCHAR) HiberIdentityVa);
  191. }