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.

283 lines
7.5 KiB

  1. /*++
  2. Module Name:
  3. intimap.c
  4. Abstract:
  5. This module initializes the system process mapping for a 64-bit Alpha
  6. system.
  7. Author:
  8. David N. Cutler (davec) 5-Jan-1998
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "bldr.h"
  14. #include "arc.h"
  15. //
  16. // Define size of page map.
  17. //
  18. #define PD_INDEX(va) (((va) >> PDI2_SHIFT) & PDI_MASK)
  19. #define PAGE_MAP_SIZE (PD_INDEX(KSEG2_BASE) - PD_INDEX(KSEG0_BASE))
  20. ARC_STATUS
  21. BlInitializeSystemProcessMap (
  22. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  23. )
  24. /*++
  25. Routine Description:
  26. This function initializes the system process map for 64-bit Alpha
  27. systems.
  28. Arguments:
  29. LoaderBlock - Supplies a pointer to the loader parameter block.
  30. Return Value:
  31. None.
  32. --*/
  33. {
  34. ULONG Base;
  35. ULONG Count;
  36. PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
  37. ULONG Index;
  38. PLIST_ENTRY ListHead;
  39. UCHAR PageMap[PAGE_MAP_SIZE];
  40. PLIST_ENTRY NextEntry;
  41. ULONG Number;
  42. PHARDWARE_PTE Pdr1;
  43. PHARDWARE_PTE Pdr2;
  44. PHARDWARE_PTE Ptp;
  45. ULONG PdrPage;
  46. ARC_STATUS Status;
  47. ULONG Total;
  48. //
  49. // On 64-bit Alpha systems a three level mapping structure is used
  50. // and up to 1gb of physical memory is identity mapped into KSEG0
  51. // for PAL code access.
  52. //
  53. // One page is required for the first level page directory.
  54. //
  55. // One page is required for the kernel second level page directory.
  56. //
  57. // One page is required for each page table page in the identify map.
  58. //
  59. // One page is required for the page table page to map the shared page.
  60. //
  61. // One page is required for the shared page.
  62. //
  63. // Locate all pages in the first 1gb of physical memory and record
  64. // page table page usage.
  65. //
  66. RtlZeroMemory(&PageMap[0], PAGE_MAP_SIZE);
  67. ListHead = &LoaderBlock->MemoryDescriptorListHead;
  68. NextEntry = ListHead->Flink;
  69. do {
  70. Descriptor = CONTAINING_RECORD(NextEntry,
  71. MEMORY_ALLOCATION_DESCRIPTOR,
  72. ListEntry);
  73. Number = Descriptor->BasePage;
  74. for (Count = 0; Count < Descriptor->PageCount; Count += 1) {
  75. Index = Number >> (PDI2_SHIFT - PTI_SHIFT);
  76. if (Index < PAGE_MAP_SIZE) {
  77. PageMap[Index] = 1;
  78. }
  79. Number += 1;
  80. }
  81. NextEntry = NextEntry->Flink;
  82. } while (NextEntry != ListHead);
  83. //
  84. // Compute the number of page table pages required to map the first
  85. // 1gb of physical memory.
  86. //
  87. Total = 4;
  88. for (Count = 0; Count < PAGE_MAP_SIZE; Count += 1) {
  89. Total += PageMap[Count];
  90. }
  91. //
  92. // Allocate a level 1 page directory page, a level 2 page directory
  93. // page, a shared page table page, a shared data page, and the required
  94. // number of pages to map up to 1gb of physical
  95. // memory.
  96. //
  97. Status = BlAllocateAnyMemory(LoaderStartupPdrPage,
  98. 0,
  99. Total,
  100. &LoaderBlock->u.Alpha.PdrPage);
  101. if (Status != ESUCCESS) {
  102. return Status;
  103. }
  104. //
  105. // Self map the level 1 directory into the level 1 directory, map the
  106. // level 2 kernel page directory page into the level 1 page directory
  107. // page, map the shared data page table page, and map all the
  108. // page table pages into the level 2 page directory page so the first 1gb
  109. // of physical memory can be accessed via KSEG0.
  110. //
  111. // Compute the address of the level one page directory page and zero
  112. // the page.
  113. //
  114. PdrPage = LoaderBlock->u.Alpha.PdrPage;
  115. Pdr1 = (PHARDWARE_PTE)(KSEG0_BASE | (PdrPage << PAGE_SHIFT));
  116. RtlZeroMemory(Pdr1, PAGE_SIZE);
  117. //
  118. // Map the level one page directory identity entry in the level one
  119. // page directory page.
  120. //
  121. Index = (PDE_BASE >> PDI1_SHIFT) & PDI_MASK;
  122. Pdr1[Index].Valid = 1;
  123. Pdr1[Index].KernelReadAccess = 1;
  124. Pdr1[Index].KernelWriteAccess = 1;
  125. Pdr1[Index].Write = 1;
  126. Pdr1[Index].PageFrameNumber = PdrPage++;
  127. //
  128. // Map the level two kernel page directory page entry in the level one
  129. // page directory page.
  130. //
  131. Index = (KSEG0_BASE >> PDI1_SHIFT) & PDI_MASK;
  132. Pdr1[Index].Valid = 1;
  133. Pdr1[Index].KernelReadAccess = 1;
  134. Pdr1[Index].KernelWriteAccess = 1;
  135. Pdr1[Index].Write = 1;
  136. Pdr1[Index].PageFrameNumber = PdrPage;
  137. //
  138. // Compute the address of the level two kernel page directory page and
  139. // zero the page.
  140. //
  141. Pdr2 = (PHARDWARE_PTE)(KSEG0_BASE | (PdrPage++ << PAGE_SHIFT));
  142. RtlZeroMemory(Pdr2, PAGE_SIZE);
  143. //
  144. // Map the shared data page table page in the level two kernel page
  145. // directory page.
  146. //
  147. Index = (KI_USER_SHARED_DATA >> PDI2_SHIFT) & PDI_MASK;
  148. Pdr2[Index].Valid = 1;
  149. Pdr2[Index].Global = 1;
  150. Pdr2[Index].KernelReadAccess = 1;
  151. Pdr2[Index].KernelWriteAccess = 1;
  152. Pdr2[Index].Write = 1;
  153. Pdr2[Index].PageFrameNumber = PdrPage;
  154. //
  155. // Compute the address of the shared data page table page and zero
  156. // the page.
  157. //
  158. Ptp = (PHARDWARE_PTE)(KSEG0_BASE | (PdrPage++ << PAGE_SHIFT));
  159. RtlZeroMemory(Ptp, PAGE_SIZE);
  160. //
  161. // Map the shared data page in the shared data page table page.
  162. //
  163. Index = (KI_USER_SHARED_DATA >> PTI_SHIFT) & PDI_MASK;
  164. Ptp[Index].Valid = 1;
  165. Ptp[Index].Global = 1;
  166. Ptp[Index].KernelReadAccess = 1;
  167. Ptp[Index].KernelWriteAccess = 1;
  168. Ptp[Index].Write = 1;
  169. Ptp[Index].PageFrameNumber = PdrPage;
  170. //
  171. // Compute the address of the shared data page and zero the page.
  172. //
  173. Ptp = (PHARDWARE_PTE)(KSEG0_BASE | (PdrPage++ << PAGE_SHIFT));
  174. RtlZeroMemory(Ptp, PAGE_SIZE);
  175. //
  176. // Construct the identity map for the first 1gb of physical memory.
  177. //
  178. Base = (KSEG0_BASE >> PDI2_SHIFT) & PDI_MASK;
  179. for (Count = 0; Count < PAGE_MAP_SIZE; Count += 1) {
  180. if (PageMap[Count] != 0) {
  181. Pdr2[Base | Count].Valid = 1;
  182. Pdr2[Base | Count].Global = 1;
  183. Pdr2[Base | Count].KernelReadAccess = 1;
  184. Pdr2[Base | Count].KernelWriteAccess = 1;
  185. Pdr2[Base | Count].Write = 1;
  186. Pdr2[Base | Count].PageFrameNumber = PdrPage;
  187. Ptp = (PHARDWARE_PTE)(KSEG0_BASE | (PdrPage << PAGE_SHIFT));
  188. RtlZeroMemory(Ptp, PAGE_SIZE);
  189. PdrPage += 1;
  190. }
  191. }
  192. //
  193. // Identity map the first 1gb of physical memory into KSEG0.
  194. //
  195. ListHead = &LoaderBlock->MemoryDescriptorListHead;
  196. NextEntry = ListHead->Flink;
  197. do {
  198. Descriptor = CONTAINING_RECORD(NextEntry,
  199. MEMORY_ALLOCATION_DESCRIPTOR,
  200. ListEntry);
  201. Number = Descriptor->BasePage;
  202. for (Count = 0; Count < Descriptor->PageCount; Count += 1) {
  203. Index = Number >> (PDI2_SHIFT - PTI_SHIFT);
  204. if (Index < PAGE_MAP_SIZE) {
  205. Ptp = (PHARDWARE_PTE)(KSEG0_BASE | (Pdr2[Base | Index].PageFrameNumber << PAGE_SHIFT));
  206. Index = Number & PDI_MASK;
  207. Ptp[Index].Valid = 1;
  208. Ptp[Index].Global = 1;
  209. Ptp[Index].KernelReadAccess = 1;
  210. Ptp[Index].KernelWriteAccess = 1;
  211. Ptp[Index].Write = 1;
  212. Ptp[Index].PageFrameNumber = Number;
  213. }
  214. Number += 1;
  215. }
  216. NextEntry = NextEntry->Flink;
  217. } while (NextEntry != ListHead);
  218. //
  219. // Set the granularity hint bits.
  220. //
  221. BlSetGranularityHints(Pdr1, Total);
  222. return ESUCCESS;
  223. }