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.

3151 lines
100 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. initia64.c
  5. Abstract:
  6. This module contains the machine dependent initialization for the
  7. memory management component. It is specifically tailored to the
  8. IA64 architecture.
  9. Author:
  10. Koichi Yamada (kyamada) 9-Jan-1996
  11. Landy Wang (landyw) 2-June-1997
  12. Revision History:
  13. --*/
  14. #include "mi.h"
  15. VOID
  16. MiBuildPageTableForLoaderMemory (
  17. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  18. );
  19. PVOID
  20. MiConvertToLoaderVirtual (
  21. IN PFN_NUMBER Page,
  22. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  23. );
  24. VOID
  25. MiRemoveLoaderSuperPages (
  26. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  27. );
  28. VOID
  29. MiCompactMemoryDescriptorList (
  30. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  31. );
  32. VOID
  33. MiInitializeTbImage (
  34. VOID
  35. );
  36. VOID
  37. MiAddTrEntry (
  38. ULONG_PTR BaseAddress,
  39. ULONG_PTR EndAddress
  40. );
  41. VOID
  42. MiComputeInitialLargePage (
  43. VOID
  44. );
  45. PVOID MiMaxWow64Pte;
  46. //
  47. // This is enabled once the memory management page table structures and TB
  48. // entries have been initialized and can be safely referenced.
  49. //
  50. LOGICAL MiMappingsInitialized = FALSE;
  51. PFN_NUMBER MmSystemParentTablePage;
  52. PFN_NUMBER MmSessionParentTablePage;
  53. REGION_MAP_INFO MmSessionMapInfo;
  54. MMPTE MiSystemSelfMappedPte;
  55. MMPTE MiUserSelfMappedPte;
  56. PFN_NUMBER MiNtoskrnlPhysicalBase;
  57. ULONG_PTR MiNtoskrnlVirtualBase;
  58. ULONG MiNtoskrnlPageShift;
  59. MMPTE MiDefaultPpe;
  60. MMPTE MiNatPte;
  61. #define _x1mb (1024*1024)
  62. #define _x1mbnp ((1024*1024) >> PAGE_SHIFT)
  63. #define _x4mb (1024*1024*4)
  64. #define _x4mbnp ((1024*1024*4) >> PAGE_SHIFT)
  65. #define _x16mb (1024*1024*16)
  66. #define _x16mbnp ((1024*1024*16) >> PAGE_SHIFT)
  67. #define _x64mb (1024*1024*64)
  68. #define _x64mbnp ((1024*1024*64) >> PAGE_SHIFT)
  69. #define _x256mb (1024*1024*256)
  70. #define _x256mbnp ((1024*1024*256) >> PAGE_SHIFT)
  71. #define _x4gb (0x100000000UI64)
  72. #define _x4gbnp (0x100000000UI64 >> PAGE_SHIFT)
  73. PMEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptor;
  74. PFN_NUMBER MiOldFreeDescriptorBase;
  75. PFN_NUMBER MiOldFreeDescriptorCount;
  76. PFN_NUMBER MiSlushDescriptorBase;
  77. PFN_NUMBER MiSlushDescriptorCount;
  78. PFN_NUMBER MiInitialLargePage;
  79. PFN_NUMBER MiInitialLargePageSize;
  80. PFN_NUMBER MxPfnAllocation;
  81. extern KEVENT MiImageMappingPteEvent;
  82. //
  83. // Examine the 8 icache & dcache TR entries looking for a match.
  84. // It is too bad the number of entries is hardcoded into the
  85. // loader block. Since it is this way, declare our own static array
  86. // and also assume also that the ITR and DTR entries are contiguous
  87. // and just keep walking into the DTR if a match cannot be found in the ITR.
  88. //
  89. #define NUMBER_OF_LOADER_TR_ENTRIES 8
  90. TR_INFO MiTrInfo[2 * NUMBER_OF_LOADER_TR_ENTRIES];
  91. TR_INFO MiBootedTrInfo[2 * NUMBER_OF_LOADER_TR_ENTRIES];
  92. PTR_INFO MiLastTrEntry;
  93. //
  94. // These variables are purely for use by the debugger.
  95. //
  96. PVOID MiKseg0Start;
  97. PVOID MiKseg0End;
  98. PFN_NUMBER MiKseg0StartFrame;
  99. PFN_NUMBER MiKseg0EndFrame;
  100. BOOLEAN MiKseg0Mapping;
  101. PFN_NUMBER
  102. MiGetNextPhysicalPage (
  103. VOID
  104. );
  105. VOID
  106. MiCompactMemoryDescriptorList (
  107. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  108. );
  109. LOGICAL
  110. MiIsRegularMemory (
  111. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  112. IN PFN_NUMBER PageFrameIndex
  113. );
  114. #ifdef ALLOC_PRAGMA
  115. #pragma alloc_text(INIT,MiInitMachineDependent)
  116. #pragma alloc_text(INIT,MiGetNextPhysicalPage)
  117. #pragma alloc_text(INIT,MiBuildPageTableForLoaderMemory)
  118. #pragma alloc_text(INIT,MiConvertToLoaderVirtual)
  119. #pragma alloc_text(INIT,MiInitializeTbImage)
  120. #pragma alloc_text(INIT,MiAddTrEntry)
  121. #pragma alloc_text(INIT,MiCompactMemoryDescriptorList)
  122. #pragma alloc_text(INIT,MiRemoveLoaderSuperPages)
  123. #pragma alloc_text(INIT,MiComputeInitialLargePage)
  124. #pragma alloc_text(INIT,MiIsRegularMemory)
  125. #endif
  126. PFN_NUMBER
  127. MiGetNextPhysicalPage (
  128. VOID
  129. )
  130. /*++
  131. Routine Description:
  132. This function returns the next physical page number from the
  133. free descriptor. If there are no physical pages left, then a
  134. bugcheck is executed since the system cannot be initialized.
  135. Arguments:
  136. None.
  137. Return Value:
  138. The next physical page number.
  139. Environment:
  140. Kernel mode.
  141. --*/
  142. {
  143. PFN_NUMBER FreePage;
  144. if (MiFreeDescriptor->PageCount == 0) {
  145. KeBugCheckEx (INSTALL_MORE_MEMORY,
  146. MmNumberOfPhysicalPages,
  147. MmLowestPhysicalPage,
  148. MmHighestPhysicalPage,
  149. 0);
  150. }
  151. FreePage = MiFreeDescriptor->BasePage;
  152. MiFreeDescriptor->PageCount -= 1;
  153. MiFreeDescriptor->BasePage += 1;
  154. return FreePage;
  155. }
  156. VOID
  157. MiComputeInitialLargePage (
  158. VOID
  159. )
  160. /*++
  161. Routine Description:
  162. This function computes the number of bytes needed to span the initial
  163. nonpaged pool and PFN database plus the color arrays. It rounds this up
  164. to a large page boundary and carves the memory from the free descriptor.
  165. If the physical memory is too sparse to use large pages for this, then
  166. fall back to using small pages. ie: we have seen an OEM machine
  167. with only 2 1gb chunks of RAM and a 275gb gap between them !
  168. Arguments:
  169. None.
  170. Return Value:
  171. None.
  172. Environment:
  173. Kernel mode, INIT only.
  174. --*/
  175. {
  176. PFN_NUMBER BasePage;
  177. PFN_NUMBER LastPage;
  178. SIZE_T NumberOfBytes;
  179. SIZE_T PfnAllocation;
  180. SIZE_T MaximumNonPagedPoolInBytesLimit;
  181. #if defined(MI_MULTINODE)
  182. PFN_NUMBER i;
  183. #endif
  184. MaximumNonPagedPoolInBytesLimit = 0;
  185. //
  186. // Non-paged pool comprises 2 chunks. The initial nonpaged pool grows
  187. // up and the expansion nonpaged pool expands downward.
  188. //
  189. // Initial non-paged pool is constructed so virtual addresses
  190. // are also physically contiguous.
  191. //
  192. if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) >
  193. (7 * (MmNumberOfPhysicalPages >> 3))) {
  194. //
  195. // More than 7/8 of memory allocated to nonpagedpool, reset to 0.
  196. //
  197. MmSizeOfNonPagedPoolInBytes = 0;
  198. }
  199. if (MmSizeOfNonPagedPoolInBytes < MmMinimumNonPagedPoolSize) {
  200. //
  201. // Calculate the size of nonpaged pool.
  202. // Use the minimum size, then for every MB above 16mb add extra pages.
  203. //
  204. MmSizeOfNonPagedPoolInBytes = MmMinimumNonPagedPoolSize;
  205. MmSizeOfNonPagedPoolInBytes +=
  206. ((MmNumberOfPhysicalPages - _x16mbnp)/_x1mbnp) *
  207. MmMinAdditionNonPagedPoolPerMb;
  208. }
  209. if (MmSizeOfNonPagedPoolInBytes > MM_MAX_INITIAL_NONPAGED_POOL) {
  210. MmSizeOfNonPagedPoolInBytes = MM_MAX_INITIAL_NONPAGED_POOL;
  211. }
  212. //
  213. // If the registry specifies a total nonpaged pool percentage cap, enforce
  214. // it here.
  215. //
  216. if (MmMaximumNonPagedPoolPercent != 0) {
  217. if (MmMaximumNonPagedPoolPercent < 5) {
  218. MmMaximumNonPagedPoolPercent = 5;
  219. }
  220. else if (MmMaximumNonPagedPoolPercent > 80) {
  221. MmMaximumNonPagedPoolPercent = 80;
  222. }
  223. //
  224. // Use the registry-expressed percentage value.
  225. //
  226. MaximumNonPagedPoolInBytesLimit =
  227. ((MmNumberOfPhysicalPages * MmMaximumNonPagedPoolPercent) / 100);
  228. MaximumNonPagedPoolInBytesLimit *= PAGE_SIZE;
  229. if (MaximumNonPagedPoolInBytesLimit < 6 * 1024 * 1024) {
  230. MaximumNonPagedPoolInBytesLimit = 6 * 1024 * 1024;
  231. }
  232. if (MmSizeOfNonPagedPoolInBytes > MaximumNonPagedPoolInBytesLimit) {
  233. MmSizeOfNonPagedPoolInBytes = MaximumNonPagedPoolInBytesLimit;
  234. }
  235. }
  236. MmSizeOfNonPagedPoolInBytes = MI_ROUND_TO_SIZE (MmSizeOfNonPagedPoolInBytes,
  237. PAGE_SIZE);
  238. //
  239. // Don't let the initial nonpaged pool choice exceed what's actually
  240. // available.
  241. //
  242. if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) > MiFreeDescriptor->PageCount / 2) {
  243. MmSizeOfNonPagedPoolInBytes = (MiFreeDescriptor->PageCount / 2) << PAGE_SHIFT;
  244. }
  245. //
  246. // Compute the secondary color value, allowing overrides from the registry.
  247. // This is because the color arrays are going to be allocated at the end
  248. // of the PFN database.
  249. //
  250. MmSecondaryColors = MmSecondaryColors >> PAGE_SHIFT;
  251. if (MmSecondaryColors == 0) {
  252. MmSecondaryColors = MM_SECONDARY_COLORS_DEFAULT;
  253. }
  254. else {
  255. //
  256. // Make sure the value is power of two and within limits.
  257. //
  258. if (((MmSecondaryColors & (MmSecondaryColors -1)) != 0) ||
  259. (MmSecondaryColors < MM_SECONDARY_COLORS_MIN) ||
  260. (MmSecondaryColors > MM_SECONDARY_COLORS_MAX)) {
  261. MmSecondaryColors = MM_SECONDARY_COLORS_DEFAULT;
  262. }
  263. }
  264. MmSecondaryColorMask = MmSecondaryColors - 1;
  265. #if defined(MI_MULTINODE)
  266. //
  267. // Determine number of bits in MmSecondayColorMask. This
  268. // is the number of bits the Node color must be shifted
  269. // by before it is included in colors.
  270. //
  271. i = MmSecondaryColorMask;
  272. MmSecondaryColorNodeShift = 0;
  273. while (i) {
  274. i >>= 1;
  275. MmSecondaryColorNodeShift += 1;
  276. }
  277. //
  278. // Adjust the number of secondary colors by the number of nodes
  279. // in the machine. The secondary color mask is NOT adjusted
  280. // as it is used to control coloring within a node. The node
  281. // color is added to the color AFTER normal color calculations
  282. // are performed.
  283. //
  284. MmSecondaryColors *= KeNumberNodes;
  285. for (i = 0; i < KeNumberNodes; i += 1) {
  286. KeNodeBlock[i]->Color = (ULONG)i;
  287. KeNodeBlock[i]->MmShiftedColor = (ULONG)(i << MmSecondaryColorNodeShift);
  288. InitializeSListHead(&KeNodeBlock[i]->DeadStackList);
  289. }
  290. #endif
  291. //
  292. // Add in the PFN database size and the array for tracking secondary colors.
  293. //
  294. PfnAllocation = MI_ROUND_TO_SIZE (((MmHighestPossiblePhysicalPage + 1) * sizeof(MMPFN)) +
  295. (MmSecondaryColors * sizeof(MMCOLOR_TABLES)*2),
  296. PAGE_SIZE);
  297. NumberOfBytes = MmSizeOfNonPagedPoolInBytes + PfnAllocation;
  298. //
  299. // Align to large page size boundary, donating any extra to the nonpaged
  300. // pool.
  301. //
  302. NumberOfBytes = MI_ROUND_TO_SIZE (NumberOfBytes, MM_MINIMUM_VA_FOR_LARGE_PAGE);
  303. MmSizeOfNonPagedPoolInBytes = NumberOfBytes - PfnAllocation;
  304. MxPfnAllocation = PfnAllocation >> PAGE_SHIFT;
  305. //
  306. // Calculate the maximum size of pool.
  307. //
  308. if (MmMaximumNonPagedPoolInBytes == 0) {
  309. //
  310. // Calculate the size of nonpaged pool, adding extra pages for
  311. // every MB above 16mb.
  312. //
  313. MmMaximumNonPagedPoolInBytes = MmDefaultMaximumNonPagedPool;
  314. ASSERT (BYTE_OFFSET (MmMaximumNonPagedPoolInBytes) == 0);
  315. MmMaximumNonPagedPoolInBytes +=
  316. ((SIZE_T)((MmNumberOfPhysicalPages - _x16mbnp)/_x1mbnp) *
  317. MmMaxAdditionNonPagedPoolPerMb);
  318. if ((MmMaximumNonPagedPoolPercent != 0) &&
  319. (MmMaximumNonPagedPoolInBytes > MaximumNonPagedPoolInBytesLimit)) {
  320. MmMaximumNonPagedPoolInBytes = MaximumNonPagedPoolInBytesLimit;
  321. }
  322. }
  323. MmMaximumNonPagedPoolInBytes = MI_ROUND_TO_SIZE (MmMaximumNonPagedPoolInBytes,
  324. MM_MINIMUM_VA_FOR_LARGE_PAGE);
  325. MmMaximumNonPagedPoolInBytes += NumberOfBytes;
  326. if (MmMaximumNonPagedPoolInBytes > MM_MAX_ADDITIONAL_NONPAGED_POOL) {
  327. MmMaximumNonPagedPoolInBytes = MM_MAX_ADDITIONAL_NONPAGED_POOL;
  328. }
  329. MiInitialLargePageSize = NumberOfBytes >> PAGE_SHIFT;
  330. if (MxPfnAllocation <= MiFreeDescriptor->PageCount / 2) {
  331. //
  332. // See if the free descriptor has enough pages of large page alignment
  333. // to satisfy our calculation.
  334. //
  335. BasePage = MI_ROUND_TO_SIZE (MiFreeDescriptor->BasePage,
  336. MM_MINIMUM_VA_FOR_LARGE_PAGE >> PAGE_SHIFT);
  337. LastPage = MiFreeDescriptor->BasePage + MiFreeDescriptor->PageCount;
  338. if ((BasePage < MiFreeDescriptor->BasePage) ||
  339. (BasePage + (NumberOfBytes >> PAGE_SHIFT) > LastPage)) {
  340. KeBugCheckEx (INSTALL_MORE_MEMORY,
  341. NumberOfBytes >> PAGE_SHIFT,
  342. MiFreeDescriptor->BasePage,
  343. MiFreeDescriptor->PageCount,
  344. 2);
  345. }
  346. if (BasePage == MiFreeDescriptor->BasePage) {
  347. //
  348. // The descriptor starts on a large page aligned boundary so
  349. // remove the large page span from the bottom of the free descriptor.
  350. //
  351. MiInitialLargePage = BasePage;
  352. MiFreeDescriptor->BasePage += (ULONG) MiInitialLargePageSize;
  353. MiFreeDescriptor->PageCount -= (ULONG) MiInitialLargePageSize;
  354. }
  355. else {
  356. if ((LastPage & ((MM_MINIMUM_VA_FOR_LARGE_PAGE >> PAGE_SHIFT) - 1)) == 0) {
  357. //
  358. // The descriptor ends on a large page aligned boundary so
  359. // remove the large page span from the top of the free descriptor.
  360. //
  361. MiInitialLargePage = LastPage - MiInitialLargePageSize;
  362. MiFreeDescriptor->PageCount -= (ULONG) MiInitialLargePageSize;
  363. }
  364. else {
  365. //
  366. // The descriptor does not start or end on a large page aligned
  367. // address so chop the descriptor. The excess slush is added to
  368. // the freelist by our caller.
  369. //
  370. MiSlushDescriptorBase = MiFreeDescriptor->BasePage;
  371. MiSlushDescriptorCount = BasePage - MiFreeDescriptor->BasePage;
  372. MiInitialLargePage = BasePage;
  373. MiFreeDescriptor->PageCount -= (ULONG) (MiInitialLargePageSize + MiSlushDescriptorCount);
  374. MiFreeDescriptor->BasePage = (ULONG) (BasePage + MiInitialLargePageSize);
  375. }
  376. }
  377. }
  378. else {
  379. //
  380. // Not enough contiguous physical memory in this machine to use large
  381. // pages for the PFN database and color heads so fall back to small.
  382. //
  383. // Continue to march on so the virtual sizes can still be computed
  384. // properly.
  385. //
  386. // Note this is not large page aligned so it can never be confused with
  387. // a valid large page start.
  388. //
  389. MiInitialLargePage = (PFN_NUMBER) -1;
  390. }
  391. MmPfnDatabase = (PMMPFN) ((PCHAR)MmNonPagedPoolEnd - MmMaximumNonPagedPoolInBytes);
  392. MmNonPagedPoolStart = (PVOID)((PCHAR) MmPfnDatabase + PfnAllocation);
  393. MmNonPagedPoolExpansionStart = (PVOID)((PCHAR) MmPfnDatabase +
  394. (MiInitialLargePageSize << PAGE_SHIFT));
  395. ASSERT (BYTE_OFFSET (MmNonPagedPoolStart) == 0);
  396. MmPageAlignedPoolBase[NonPagedPool] = MmNonPagedPoolStart;
  397. MmMaximumNonPagedPoolInBytes = ((PCHAR) MmNonPagedPoolEnd - (PCHAR) MmNonPagedPoolStart);
  398. MmMaximumNonPagedPoolInPages = (MmMaximumNonPagedPoolInBytes >> PAGE_SHIFT);
  399. return;
  400. }
  401. LOGICAL
  402. MiIsRegularMemory (
  403. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  404. IN PFN_NUMBER PageFrameIndex
  405. )
  406. /*++
  407. Routine Description:
  408. This routine checks whether the argument page frame index represents
  409. regular memory in the loader descriptor block. It is only used very
  410. early during Phase0 init because the MmPhysicalMemoryBlock is not yet
  411. initialized.
  412. Arguments:
  413. LoaderBlock - Supplies a pointer to the firmware setup loader block.
  414. PageFrameIndex - Supplies the page frame index to check.
  415. Return Value:
  416. TRUE if the frame represents regular memory, FALSE if not.
  417. Environment:
  418. Kernel mode.
  419. --*/
  420. {
  421. PLIST_ENTRY NextMd;
  422. PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
  423. NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
  424. while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
  425. MemoryDescriptor = CONTAINING_RECORD (NextMd,
  426. MEMORY_ALLOCATION_DESCRIPTOR,
  427. ListEntry);
  428. if (PageFrameIndex >= MemoryDescriptor->BasePage) {
  429. if (PageFrameIndex < MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) {
  430. if ((MemoryDescriptor->MemoryType == LoaderFirmwarePermanent) ||
  431. (MemoryDescriptor->MemoryType == LoaderBBTMemory) ||
  432. (MemoryDescriptor->MemoryType == LoaderSpecialMemory)) {
  433. //
  434. // This page lies in a memory descriptor for which we will
  435. // never create PFN entries, hence return FALSE.
  436. //
  437. break;
  438. }
  439. return TRUE;
  440. }
  441. }
  442. else {
  443. //
  444. // Since the loader memory list is sorted in ascending order,
  445. // the requested page must not be in the loader list at all.
  446. //
  447. break;
  448. }
  449. NextMd = MemoryDescriptor->ListEntry.Flink;
  450. }
  451. //
  452. // The final check before returning FALSE is to ensure that the requested
  453. // page wasn't one of the ones we used to normal-map the loader mappings,
  454. // etc.
  455. //
  456. if ((PageFrameIndex >= MiOldFreeDescriptorBase) &&
  457. (PageFrameIndex < MiOldFreeDescriptorBase + MiOldFreeDescriptorCount)) {
  458. return TRUE;
  459. }
  460. if ((PageFrameIndex >= MiSlushDescriptorBase) &&
  461. (PageFrameIndex < MiSlushDescriptorBase + MiSlushDescriptorCount)) {
  462. return TRUE;
  463. }
  464. return FALSE;
  465. }
  466. VOID
  467. MiInitMachineDependent (
  468. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  469. )
  470. /*++
  471. Routine Description:
  472. This routine performs the necessary operations to enable virtual
  473. memory. This includes building the page directory page, building
  474. page table pages to map the code section, the data section, the
  475. stack section and the trap handler.
  476. It also initializes the PFN database and populates the free list.
  477. Arguments:
  478. LoaderBlock - Supplies a pointer to the firmware setup loader block.
  479. Return Value:
  480. None.
  481. Environment:
  482. Kernel mode.
  483. N.B. This routine uses memory from the loader block descriptors, but
  484. the descriptors themselves must be restored prior to return as our caller
  485. walks them to create the MmPhysicalMemoryBlock.
  486. --*/
  487. {
  488. PMMPFN BasePfn;
  489. PMMPFN TopPfn;
  490. PMMPFN BottomPfn;
  491. SIZE_T Range;
  492. PFN_NUMBER BasePage;
  493. PFN_COUNT PageCount;
  494. PHYSICAL_ADDRESS MaxHotPlugMemoryAddress;
  495. PFN_COUNT FreeNextPhysicalPage;
  496. PFN_COUNT FreeNumberOfPages;
  497. PFN_NUMBER i;
  498. ULONG j;
  499. PFN_NUMBER PdePageNumber;
  500. PFN_NUMBER PdePage;
  501. PFN_NUMBER PpePage;
  502. PFN_NUMBER PageFrameIndex;
  503. PFN_NUMBER NextPhysicalPage;
  504. SPFN_NUMBER PfnAllocation;
  505. SIZE_T MaxPool;
  506. PEPROCESS CurrentProcess;
  507. PFN_NUMBER MostFreePage;
  508. PLIST_ENTRY NextMd;
  509. PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
  510. MMPTE TempPde;
  511. MMPTE TempPte;
  512. PMMPTE PointerPde;
  513. PMMPTE PointerPte;
  514. PMMPTE LastPte;
  515. PMMPTE Pde;
  516. PMMPTE StartPde;
  517. PMMPTE StartPpe;
  518. PMMPTE EndPde;
  519. PMMPFN Pfn1;
  520. PMMPFN Pfn2;
  521. PMMPFN Pfn3;
  522. ULONG First;
  523. PVOID SystemPteStart;
  524. ULONG ReturnedLength;
  525. NTSTATUS status;
  526. PTR_INFO ItrInfo;
  527. MostFreePage = 0;
  528. //
  529. // Initialize some variables so they do not need to be constantly
  530. // recalculated throughout the life of the system.
  531. //
  532. MiMaxWow64Pte = (PVOID) MiGetPteAddress ((PVOID)_4gb);
  533. //
  534. // Initialize the kernel mapping info.
  535. //
  536. ItrInfo = &LoaderBlock->u.Ia64.ItrInfo[ITR_KERNEL_INDEX];
  537. MiNtoskrnlPhysicalBase = ItrInfo->PhysicalAddress;
  538. MiNtoskrnlVirtualBase = ItrInfo->VirtualAddress;
  539. MiNtoskrnlPageShift = ItrInfo->PageSize;
  540. //
  541. // Initialize MmDebugPte and MmCrashDumpPte.
  542. //
  543. MmDebugPte = MiGetPteAddress (MM_DEBUG_VA);
  544. MmCrashDumpPte = MiGetPteAddress (MM_CRASH_DUMP_VA);
  545. //
  546. // Set TempPte to ValidKernelPte for future use.
  547. //
  548. TempPte = ValidKernelPte;
  549. //
  550. // Compact the memory descriptor list from the loader.
  551. //
  552. MiCompactMemoryDescriptorList (LoaderBlock);
  553. //
  554. // Get the lower bound of the free physical memory and the
  555. // number of physical pages by walking the memory descriptor lists.
  556. //
  557. NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
  558. while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
  559. MemoryDescriptor = CONTAINING_RECORD (NextMd,
  560. MEMORY_ALLOCATION_DESCRIPTOR,
  561. ListEntry);
  562. if ((MemoryDescriptor->MemoryType != LoaderBBTMemory) &&
  563. (MemoryDescriptor->MemoryType != LoaderFirmwarePermanent) &&
  564. (MemoryDescriptor->MemoryType != LoaderSpecialMemory)) {
  565. BasePage = MemoryDescriptor->BasePage;
  566. PageCount = MemoryDescriptor->PageCount;
  567. //
  568. // This check results in /BURNMEMORY chunks not being counted.
  569. //
  570. if (MemoryDescriptor->MemoryType != LoaderBad) {
  571. MmNumberOfPhysicalPages += PageCount;
  572. }
  573. if (BasePage < MmLowestPhysicalPage) {
  574. MmLowestPhysicalPage = BasePage;
  575. }
  576. if (MemoryDescriptor->MemoryType != LoaderBad) {
  577. if ((BasePage + PageCount) > MmHighestPhysicalPage) {
  578. MmHighestPhysicalPage = BasePage + PageCount -1;
  579. }
  580. }
  581. if ((MemoryDescriptor->MemoryType == LoaderFree) ||
  582. (MemoryDescriptor->MemoryType == LoaderLoadedProgram) ||
  583. (MemoryDescriptor->MemoryType == LoaderFirmwareTemporary) ||
  584. (MemoryDescriptor->MemoryType == LoaderOsloaderStack)) {
  585. //
  586. // Deliberately use >= instead of just > to force our allocation
  587. // as high as physically possible. This is to leave low pages
  588. // for drivers which may require them.
  589. //
  590. if (PageCount >= MostFreePage) {
  591. MostFreePage = PageCount;
  592. MiFreeDescriptor = MemoryDescriptor;
  593. }
  594. }
  595. }
  596. NextMd = MemoryDescriptor->ListEntry.Flink;
  597. }
  598. if (MiFreeDescriptor == NULL) {
  599. KeBugCheckEx (INSTALL_MORE_MEMORY,
  600. MmNumberOfPhysicalPages,
  601. MmLowestPhysicalPage,
  602. MmHighestPhysicalPage,
  603. 1);
  604. }
  605. //
  606. // MmDynamicPfn may have been initialized based on the registry to
  607. // a value representing the highest physical address in gigabytes.
  608. //
  609. MmDynamicPfn *= ((1024 * 1024 * 1024) / PAGE_SIZE);
  610. //
  611. // Retrieve highest hot plug memory range from the HAL if
  612. // available and not otherwise retrieved from the registry.
  613. //
  614. if (MmDynamicPfn == 0) {
  615. status = HalQuerySystemInformation (HalQueryMaxHotPlugMemoryAddress,
  616. sizeof(PHYSICAL_ADDRESS),
  617. (PPHYSICAL_ADDRESS) &MaxHotPlugMemoryAddress,
  618. &ReturnedLength);
  619. if (NT_SUCCESS(status)) {
  620. ASSERT (ReturnedLength == sizeof(PHYSICAL_ADDRESS));
  621. MmDynamicPfn = (PFN_NUMBER) (MaxHotPlugMemoryAddress.QuadPart / PAGE_SIZE);
  622. }
  623. }
  624. if (MmDynamicPfn != 0) {
  625. MmHighestPossiblePhysicalPage = MI_DTC_MAX_PAGES - 1;
  626. if (MmDynamicPfn - 1 < MmHighestPossiblePhysicalPage) {
  627. if (MmDynamicPfn - 1 < MmHighestPhysicalPage) {
  628. MmDynamicPfn = MmHighestPhysicalPage + 1;
  629. }
  630. MmHighestPossiblePhysicalPage = MmDynamicPfn - 1;
  631. }
  632. }
  633. else {
  634. MmHighestPossiblePhysicalPage = MmHighestPhysicalPage;
  635. }
  636. //
  637. // Only machines with at least 5GB of physical memory get to use this.
  638. //
  639. if (strstr(LoaderBlock->LoadOptions, "NOLOWMEM")) {
  640. if (MmNumberOfPhysicalPages >= ((ULONGLONG)5 * 1024 * 1024 * 1024 / PAGE_SIZE)) {
  641. MiNoLowMemory = (PFN_NUMBER)((ULONGLONG)_4gb / PAGE_SIZE);
  642. }
  643. }
  644. if (MiNoLowMemory != 0) {
  645. MmMakeLowMemory = TRUE;
  646. }
  647. //
  648. // Initialize the Phase0 page allocation structures.
  649. //
  650. MiOldFreeDescriptorCount = MiFreeDescriptor->PageCount;
  651. MiOldFreeDescriptorBase = MiFreeDescriptor->BasePage;
  652. //
  653. // Compute the size of the initial nonpaged pool and the PFN database.
  654. // This is because we will remove this amount from the free descriptor
  655. // first and subsequently map it with large TB entries (so it requires
  656. // natural alignment & size, thus take it before other allocations chip
  657. // away at the descriptor).
  658. //
  659. MiComputeInitialLargePage ();
  660. //
  661. // Build the parent directory page table for kernel space.
  662. //
  663. PdePageNumber = (PFN_NUMBER)LoaderBlock->u.Ia64.PdrPage;
  664. MmSystemParentTablePage = MiGetNextPhysicalPage ();
  665. RtlZeroMemory (KSEG_ADDRESS(MmSystemParentTablePage), PAGE_SIZE);
  666. TempPte.u.Hard.PageFrameNumber = MmSystemParentTablePage;
  667. MiSystemSelfMappedPte = TempPte;
  668. KeFillFixedEntryTb ((PHARDWARE_PTE)&TempPte,
  669. (PVOID)PDE_KTBASE,
  670. PAGE_SHIFT,
  671. DTR_KTBASE_INDEX_TMP);
  672. //
  673. // Initialize the selfmap PPE entry in the kernel parent directory table.
  674. //
  675. PointerPte = MiGetPteAddress ((PVOID)PDE_KTBASE);
  676. MI_WRITE_VALID_PTE (PointerPte, TempPte);
  677. //
  678. // Initialize the kernel image PPE entry in the parent directory table.
  679. //
  680. PointerPte = MiGetPteAddress ((PVOID)PDE_KBASE);
  681. TempPte.u.Hard.PageFrameNumber = PdePageNumber;
  682. MI_WRITE_VALID_PTE (PointerPte, TempPte);
  683. //
  684. // Build the parent directory page table for user space.
  685. //
  686. NextPhysicalPage = MiGetNextPhysicalPage ();
  687. RtlZeroMemory (KSEG_ADDRESS(NextPhysicalPage), PAGE_SIZE);
  688. TempPte.u.Hard.PageFrameNumber = NextPhysicalPage;
  689. CurrentProcess = PsGetCurrentProcess ();
  690. INITIALIZE_DIRECTORY_TABLE_BASE (&CurrentProcess->Pcb.DirectoryTableBase[0],
  691. NextPhysicalPage);
  692. MiUserSelfMappedPte = TempPte;
  693. KeFillFixedEntryTb ((PHARDWARE_PTE)&TempPte,
  694. (PVOID)PDE_UTBASE,
  695. PAGE_SHIFT,
  696. DTR_UTBASE_INDEX_TMP);
  697. //
  698. // Initialize the selfmap PPE entry in the user parent directory table.
  699. //
  700. PointerPte = MiGetPteAddress ((PVOID)PDE_UTBASE);
  701. MI_WRITE_VALID_PTE (PointerPte, TempPte);
  702. //
  703. // Build the parent directory page table for win32k (session) space.
  704. //
  705. // TS will only allocate a map for session space when each one is
  706. // actually created by smss.
  707. //
  708. // Note TS never maps session space into the system process.
  709. // The system process is kept Hydra-free so that trims can happen
  710. // properly and also so that renegade worker items are caught.
  711. //
  712. NextPhysicalPage = MiGetNextPhysicalPage ();
  713. RtlZeroMemory (KSEG_ADDRESS(NextPhysicalPage), PAGE_SIZE);
  714. TempPte.u.Hard.PageFrameNumber = NextPhysicalPage;
  715. MmSessionParentTablePage = NextPhysicalPage;
  716. INITIALIZE_DIRECTORY_TABLE_BASE (&CurrentProcess->Pcb.SessionParentBase,
  717. NextPhysicalPage);
  718. KeFillFixedEntryTb ((PHARDWARE_PTE)&TempPte,
  719. (PVOID)PDE_STBASE,
  720. PAGE_SHIFT,
  721. DTR_STBASE_INDEX);
  722. //
  723. // Initialize the selfmap PPE entry in the Hydra parent directory table.
  724. //
  725. PointerPte = MiGetPteAddress ((PVOID)PDE_STBASE);
  726. MI_WRITE_VALID_PTE (PointerPte, TempPte);
  727. //
  728. // Initialize the default PPE for the unused regions.
  729. //
  730. NextPhysicalPage = MiGetNextPhysicalPage ();
  731. PointerPte = KSEG_ADDRESS(NextPhysicalPage);
  732. RtlZeroMemory ((PVOID)PointerPte, PAGE_SIZE);
  733. TempPte.u.Hard.PageFrameNumber = NextPhysicalPage;
  734. MiDefaultPpe = TempPte;
  735. PointerPte[MiGetPpeOffset(PDE_TBASE)] = TempPte;
  736. //
  737. // Build a PTE for the EPC page so an accidental ITR purge doesn't
  738. // render things undebuggable.
  739. //
  740. PointerPte = MiGetPteAddress((PVOID)MM_EPC_VA);
  741. TempPte.u.Hard.PageFrameNumber =
  742. MI_CONVERT_PHYSICAL_TO_PFN((PVOID)((PPLABEL_DESCRIPTOR)(ULONG_PTR)KiNormalSystemCall)->EntryPoint);
  743. MI_WRITE_VALID_PTE (PointerPte, TempPte);
  744. //
  745. // Build a PTE for the PCR page so an accidental ITR purge doesn't
  746. // render things undebuggable.
  747. //
  748. PointerPte = MiGetPteAddress ((PVOID)KIPCR);
  749. TempPte.u.Hard.PageFrameNumber = MI_CONVERT_PHYSICAL_TO_PFN (KiProcessorBlock[0]);
  750. MI_WRITE_VALID_PTE (PointerPte, TempPte);
  751. //
  752. // Initialize the NAT Page entry for null address references.
  753. //
  754. TempPte.u.Hard.PageFrameNumber = MiGetNextPhysicalPage ();
  755. TempPte.u.Hard.Cache = MM_PTE_CACHE_NATPAGE;
  756. MiNatPte = TempPte;
  757. //
  758. // Calculate the starting address for the system PTE pool which is
  759. // right below the nonpaged pool.
  760. //
  761. MmNonPagedSystemStart = (PVOID)(((ULONG_PTR)MmPfnDatabase -
  762. (((ULONG_PTR)MmNumberOfSystemPtes + 1) * PAGE_SIZE)) &
  763. (~PAGE_DIRECTORY2_MASK));
  764. if (MmNonPagedSystemStart < MM_LOWEST_NONPAGED_SYSTEM_START) {
  765. MmNonPagedSystemStart = MM_LOWEST_NONPAGED_SYSTEM_START;
  766. MmNumberOfSystemPtes = (ULONG)(((ULONG_PTR)MmPfnDatabase -
  767. (ULONG_PTR)MmNonPagedSystemStart) >> PAGE_SHIFT)-1;
  768. ASSERT (MmNumberOfSystemPtes > 1000);
  769. }
  770. //
  771. // Snap the system PTE start address as page directories and tables
  772. // will be preallocated for this range.
  773. //
  774. SystemPteStart = (PVOID) MmNonPagedSystemStart;
  775. //
  776. // If special pool and/or the driver verifier is enabled, reserve
  777. // extra virtual address space for special pooling now. For now,
  778. // arbitrarily don't let it be larger than paged pool (128gb).
  779. //
  780. if ((MmVerifyDriverBufferLength != (ULONG)-1) ||
  781. ((MmSpecialPoolTag != 0) && (MmSpecialPoolTag != (ULONG)-1))) {
  782. if (MmNonPagedSystemStart > MM_LOWEST_NONPAGED_SYSTEM_START) {
  783. MaxPool = (ULONG_PTR)MmNonPagedSystemStart -
  784. (ULONG_PTR)MM_LOWEST_NONPAGED_SYSTEM_START;
  785. if (MaxPool > MM_MAX_PAGED_POOL) {
  786. MaxPool = MM_MAX_PAGED_POOL;
  787. }
  788. MmNonPagedSystemStart = (PVOID)((ULONG_PTR)MmNonPagedSystemStart - MaxPool);
  789. }
  790. else {
  791. //
  792. // This is a pretty large machine. Take some of the system
  793. // PTEs and reuse them for special pool.
  794. //
  795. MaxPool = (4 * _x4gb);
  796. ASSERT ((PVOID)MmPfnDatabase > (PVOID)((PCHAR)MmNonPagedSystemStart + MaxPool));
  797. SystemPteStart = (PVOID)((PCHAR)MmNonPagedSystemStart + MaxPool);
  798. MmNumberOfSystemPtes = (ULONG)(((ULONG_PTR)MmPfnDatabase -
  799. (ULONG_PTR) SystemPteStart) >> PAGE_SHIFT)-1;
  800. }
  801. MmSpecialPoolStart = MmNonPagedSystemStart;
  802. MmSpecialPoolEnd = (PVOID)((ULONG_PTR)MmNonPagedSystemStart + MaxPool);
  803. }
  804. //
  805. // Map the hyper space page directory page into the top level parent
  806. // directory & the hyper space page table page into the page directory.
  807. // Additional page parents, directories & tables are set up later
  808. // on during individual process working set initialization.
  809. //
  810. TempPte = ValidPdePde;
  811. StartPpe = MiGetPpeAddress (HYPER_SPACE);
  812. if (StartPpe->u.Hard.Valid == 0) {
  813. ASSERT (StartPpe->u.Long == 0);
  814. NextPhysicalPage = MiGetNextPhysicalPage ();
  815. RtlZeroMemory (KSEG_ADDRESS(NextPhysicalPage), PAGE_SIZE);
  816. TempPte.u.Hard.PageFrameNumber = NextPhysicalPage;
  817. MI_WRITE_VALID_PTE (StartPpe, TempPte);
  818. }
  819. StartPde = MiGetPdeAddress (HYPER_SPACE);
  820. NextPhysicalPage = MiGetNextPhysicalPage ();
  821. RtlZeroMemory (KSEG_ADDRESS(NextPhysicalPage), PAGE_SIZE);
  822. TempPte.u.Hard.PageFrameNumber = NextPhysicalPage;
  823. MI_WRITE_VALID_PTE (StartPde, TempPte);
  824. //
  825. // Allocate page directory pages for the initial large page allocation.
  826. // Initial nonpaged pool, the PFN database & the color arrays will be put
  827. // here.
  828. //
  829. TempPte = ValidKernelPte;
  830. TempPde = ValidKernelPde;
  831. PageFrameIndex = MiInitialLargePage;
  832. if (MiInitialLargePage != (PFN_NUMBER) -1) {
  833. StartPpe = MiGetPpeAddress (MmPfnDatabase);
  834. StartPde = MiGetPdeAddress (MmPfnDatabase);
  835. EndPde = MiGetPdeAddress ((PVOID)((ULONG_PTR)MmPfnDatabase +
  836. (MiInitialLargePageSize << PAGE_SHIFT) - 1));
  837. MI_MAKE_PDE_MAP_LARGE_PAGE (&TempPde);
  838. RtlZeroMemory (KSEG_ADDRESS(PageFrameIndex),
  839. MiInitialLargePageSize << PAGE_SHIFT);
  840. }
  841. else {
  842. StartPpe = MiGetPpeAddress (MmNonPagedPoolStart);
  843. StartPde = MiGetPdeAddress (MmNonPagedPoolStart);
  844. EndPde = MiGetPdeAddress ((PVOID)((ULONG_PTR)MmNonPagedPoolStart +
  845. (MmSizeOfNonPagedPoolInBytes - 1)));
  846. }
  847. First = (StartPpe->u.Hard.Valid == 0) ? TRUE : FALSE;
  848. while (StartPde <= EndPde) {
  849. if (First == TRUE || MiIsPteOnPdeBoundary(StartPde)) {
  850. First = FALSE;
  851. StartPpe = MiGetPteAddress(StartPde);
  852. if (StartPpe->u.Hard.Valid == 0) {
  853. NextPhysicalPage = MiGetNextPhysicalPage ();
  854. RtlZeroMemory (KSEG_ADDRESS(NextPhysicalPage), PAGE_SIZE);
  855. TempPte.u.Hard.PageFrameNumber = NextPhysicalPage;
  856. MI_WRITE_VALID_PTE (StartPpe, TempPte);
  857. }
  858. }
  859. ASSERT (StartPde->u.Hard.Valid == 0);
  860. if (MiInitialLargePage != (PFN_NUMBER) -1) {
  861. TempPde.u.Hard.PageFrameNumber = PageFrameIndex;
  862. PageFrameIndex += (MM_VA_MAPPED_BY_PDE >> PAGE_SHIFT);
  863. MI_WRITE_VALID_PTE (StartPde, TempPde);
  864. }
  865. else {
  866. //
  867. // Allocate a page table page here since we're not using large
  868. // pages.
  869. //
  870. NextPhysicalPage = MiGetNextPhysicalPage ();
  871. RtlZeroMemory (KSEG_ADDRESS(NextPhysicalPage), PAGE_SIZE);
  872. TempPde.u.Hard.PageFrameNumber = NextPhysicalPage;
  873. MI_WRITE_VALID_PTE (StartPde, TempPde);
  874. //
  875. // Allocate data pages here since we're not using large pages.
  876. //
  877. PointerPte = MiGetVirtualAddressMappedByPte (StartPde);
  878. for (i = 0; i < PTE_PER_PAGE; i += 1) {
  879. NextPhysicalPage = MiGetNextPhysicalPage ();
  880. RtlZeroMemory (KSEG_ADDRESS(NextPhysicalPage), PAGE_SIZE);
  881. TempPte.u.Hard.PageFrameNumber = NextPhysicalPage;
  882. MI_WRITE_VALID_PTE (PointerPte, TempPte);
  883. PointerPte += 1;
  884. }
  885. }
  886. StartPde += 1;
  887. }
  888. //
  889. // Allocate page directory and page table pages for system PTEs and
  890. // expansion nonpaged pool (but not the special pool area). Note
  891. // the initial nonpaged pool, PFN database & color arrays initialized
  892. // above are skipped here by virtue of their PPE/PDEs being valid.
  893. //
  894. TempPte = ValidKernelPte;
  895. StartPpe = MiGetPpeAddress (SystemPteStart);
  896. StartPde = MiGetPdeAddress (SystemPteStart);
  897. EndPde = MiGetPdeAddress ((PVOID)((ULONG_PTR)MmNonPagedPoolEnd - 1));
  898. First = (StartPpe->u.Hard.Valid == 0) ? TRUE : FALSE;
  899. while (StartPde <= EndPde) {
  900. if (First == TRUE || MiIsPteOnPdeBoundary(StartPde)) {
  901. First = FALSE;
  902. StartPpe = MiGetPteAddress(StartPde);
  903. if (StartPpe->u.Hard.Valid == 0) {
  904. NextPhysicalPage = MiGetNextPhysicalPage ();
  905. RtlZeroMemory (KSEG_ADDRESS(NextPhysicalPage), PAGE_SIZE);
  906. TempPte.u.Hard.PageFrameNumber = NextPhysicalPage;
  907. MI_WRITE_VALID_PTE (StartPpe, TempPte);
  908. }
  909. }
  910. if (StartPde->u.Hard.Valid == 0) {
  911. NextPhysicalPage = MiGetNextPhysicalPage ();
  912. RtlZeroMemory (KSEG_ADDRESS(NextPhysicalPage), PAGE_SIZE);
  913. TempPte.u.Hard.PageFrameNumber = NextPhysicalPage;
  914. MI_WRITE_VALID_PTE (StartPde, TempPte);
  915. }
  916. StartPde += 1;
  917. }
  918. MiBuildPageTableForLoaderMemory (LoaderBlock);
  919. MiRemoveLoaderSuperPages (LoaderBlock);
  920. //
  921. // Remove the temporary super pages for the root page table pages,
  922. // and remap them with DTR_KTBASE_INDEX and DTR_UTBASE_INDEX.
  923. //
  924. KiFlushFixedDataTb (FALSE, (PVOID)PDE_KTBASE);
  925. KiFlushFixedDataTb (FALSE, (PVOID)PDE_UTBASE);
  926. KeFillFixedEntryTb ((PHARDWARE_PTE)&MiSystemSelfMappedPte,
  927. (PVOID)PDE_KTBASE,
  928. PAGE_SHIFT,
  929. DTR_KTBASE_INDEX);
  930. KeFillFixedEntryTb ((PHARDWARE_PTE)&MiUserSelfMappedPte,
  931. (PVOID)PDE_UTBASE,
  932. PAGE_SHIFT,
  933. DTR_UTBASE_INDEX);
  934. MiInitializeTbImage ();
  935. MiMappingsInitialized = TRUE;
  936. //
  937. // As only the initial nonpaged pool is mapped through superpages,
  938. // MmSubsectionTopPage is always set to zero.
  939. //
  940. MmSubsectionBase = (ULONG_PTR) MmNonPagedPoolStart;
  941. MmSubsectionTopPage = 0;
  942. //
  943. // Add the array for tracking secondary colors to the end of
  944. // the PFN database.
  945. //
  946. MmFreePagesByColor[0] = (PMMCOLOR_TABLES)
  947. &MmPfnDatabase[MmHighestPossiblePhysicalPage + 1];
  948. if (MiInitialLargePage == (PFN_NUMBER) -1) {
  949. //
  950. // Large pages were not used because this machine's physical memory
  951. // was not contiguous enough.
  952. //
  953. // Go through the memory descriptors and for each physical page make
  954. // sure the PFN database has a valid PTE to map it. This allows
  955. // machines with sparse physical memory to have a minimal PFN database.
  956. //
  957. FreeNextPhysicalPage = MiFreeDescriptor->BasePage;
  958. FreeNumberOfPages = MiFreeDescriptor->PageCount;
  959. NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
  960. while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
  961. MemoryDescriptor = CONTAINING_RECORD(NextMd,
  962. MEMORY_ALLOCATION_DESCRIPTOR,
  963. ListEntry);
  964. if ((MemoryDescriptor->MemoryType == LoaderFirmwarePermanent) ||
  965. (MemoryDescriptor->MemoryType == LoaderBBTMemory) ||
  966. (MemoryDescriptor->MemoryType == LoaderSpecialMemory)) {
  967. //
  968. // Skip these ranges.
  969. //
  970. NextMd = MemoryDescriptor->ListEntry.Flink;
  971. continue;
  972. }
  973. //
  974. // Temporarily add back in the memory allocated since Phase 0
  975. // began so PFN entries for it will be created and mapped.
  976. //
  977. // Note actual PFN entry allocations must be done carefully as
  978. // memory from the descriptor itself could get used to map
  979. // the PFNs for the descriptor !
  980. //
  981. if (MemoryDescriptor == MiFreeDescriptor) {
  982. BasePage = MiOldFreeDescriptorBase;
  983. PageCount = (PFN_COUNT) MiOldFreeDescriptorCount;
  984. }
  985. else {
  986. BasePage = MemoryDescriptor->BasePage;
  987. PageCount = MemoryDescriptor->PageCount;
  988. }
  989. PointerPte = MiGetPteAddress (MI_PFN_ELEMENT(BasePage));
  990. LastPte = MiGetPteAddress (((PCHAR)(MI_PFN_ELEMENT(
  991. BasePage + PageCount))) - 1);
  992. while (PointerPte <= LastPte) {
  993. StartPpe = MiGetPdeAddress (PointerPte);
  994. if (StartPpe->u.Hard.Valid == 0) {
  995. TempPte.u.Hard.PageFrameNumber = FreeNextPhysicalPage;
  996. ASSERT (FreeNumberOfPages != 0);
  997. FreeNextPhysicalPage += 1;
  998. FreeNumberOfPages -= 1;
  999. if (FreeNumberOfPages == 0) {
  1000. KeBugCheckEx (INSTALL_MORE_MEMORY,
  1001. MmNumberOfPhysicalPages,
  1002. FreeNumberOfPages,
  1003. MiOldFreeDescriptorCount,
  1004. 3);
  1005. }
  1006. MI_WRITE_VALID_PTE (StartPpe, TempPte);
  1007. RtlZeroMemory (MiGetVirtualAddressMappedByPte (StartPpe),
  1008. PAGE_SIZE);
  1009. }
  1010. StartPde = MiGetPteAddress (PointerPte);
  1011. if (StartPde->u.Hard.Valid == 0) {
  1012. TempPte.u.Hard.PageFrameNumber = FreeNextPhysicalPage;
  1013. ASSERT (FreeNumberOfPages != 0);
  1014. FreeNextPhysicalPage += 1;
  1015. FreeNumberOfPages -= 1;
  1016. if (FreeNumberOfPages == 0) {
  1017. KeBugCheckEx (INSTALL_MORE_MEMORY,
  1018. MmNumberOfPhysicalPages,
  1019. FreeNumberOfPages,
  1020. MiOldFreeDescriptorCount,
  1021. 3);
  1022. }
  1023. MI_WRITE_VALID_PTE (StartPde, TempPte);
  1024. RtlZeroMemory (MiGetVirtualAddressMappedByPte (StartPde),
  1025. PAGE_SIZE);
  1026. }
  1027. if (PointerPte->u.Hard.Valid == 0) {
  1028. TempPte.u.Hard.PageFrameNumber = FreeNextPhysicalPage;
  1029. ASSERT (FreeNumberOfPages != 0);
  1030. FreeNextPhysicalPage += 1;
  1031. FreeNumberOfPages -= 1;
  1032. if (FreeNumberOfPages == 0) {
  1033. KeBugCheckEx (INSTALL_MORE_MEMORY,
  1034. MmNumberOfPhysicalPages,
  1035. FreeNumberOfPages,
  1036. MiOldFreeDescriptorCount,
  1037. 3);
  1038. }
  1039. MI_WRITE_VALID_PTE (PointerPte, TempPte);
  1040. RtlZeroMemory (MiGetVirtualAddressMappedByPte (PointerPte),
  1041. PAGE_SIZE);
  1042. }
  1043. PointerPte += 1;
  1044. }
  1045. NextMd = MemoryDescriptor->ListEntry.Flink;
  1046. }
  1047. //
  1048. // Ensure the color arrays are mapped.
  1049. //
  1050. PointerPte = MiGetPteAddress (MmFreePagesByColor[0]);
  1051. LastPte = MiGetPteAddress (&MmFreePagesByColor[StandbyPageList][MmSecondaryColors]);
  1052. if (LastPte != PAGE_ALIGN (LastPte)) {
  1053. LastPte += 1;
  1054. }
  1055. StartPpe = MiGetPdeAddress (PointerPte);
  1056. PointerPde = MiGetPteAddress (PointerPte);
  1057. while (PointerPte < LastPte) {
  1058. if (StartPpe->u.Hard.Valid == 0) {
  1059. TempPte.u.Hard.PageFrameNumber = FreeNextPhysicalPage;
  1060. ASSERT (FreeNumberOfPages != 0);
  1061. FreeNextPhysicalPage += 1;
  1062. FreeNumberOfPages -= 1;
  1063. if (FreeNumberOfPages == 0) {
  1064. KeBugCheckEx (INSTALL_MORE_MEMORY,
  1065. MmNumberOfPhysicalPages,
  1066. FreeNumberOfPages,
  1067. MiOldFreeDescriptorCount,
  1068. 3);
  1069. }
  1070. MI_WRITE_VALID_PTE (StartPpe, TempPte);
  1071. RtlZeroMemory (MiGetVirtualAddressMappedByPte (StartPpe), PAGE_SIZE);
  1072. }
  1073. if (PointerPde->u.Hard.Valid == 0) {
  1074. TempPte.u.Hard.PageFrameNumber = FreeNextPhysicalPage;
  1075. ASSERT (FreeNumberOfPages != 0);
  1076. FreeNextPhysicalPage += 1;
  1077. FreeNumberOfPages -= 1;
  1078. if (FreeNumberOfPages == 0) {
  1079. KeBugCheckEx (INSTALL_MORE_MEMORY,
  1080. MmNumberOfPhysicalPages,
  1081. FreeNumberOfPages,
  1082. MiOldFreeDescriptorCount,
  1083. 3);
  1084. }
  1085. MI_WRITE_VALID_PTE (PointerPde, TempPte);
  1086. RtlZeroMemory (MiGetVirtualAddressMappedByPte (PointerPde), PAGE_SIZE);
  1087. }
  1088. if (PointerPte->u.Hard.Valid == 0) {
  1089. TempPte.u.Hard.PageFrameNumber = FreeNextPhysicalPage;
  1090. ASSERT (FreeNumberOfPages != 0);
  1091. FreeNextPhysicalPage += 1;
  1092. FreeNumberOfPages -= 1;
  1093. if (FreeNumberOfPages == 0) {
  1094. KeBugCheckEx (INSTALL_MORE_MEMORY,
  1095. MmNumberOfPhysicalPages,
  1096. FreeNumberOfPages,
  1097. MiOldFreeDescriptorCount,
  1098. 3);
  1099. }
  1100. MI_WRITE_VALID_PTE (PointerPte, TempPte);
  1101. RtlZeroMemory (MiGetVirtualAddressMappedByPte (PointerPte), PAGE_SIZE);
  1102. }
  1103. PointerPte += 1;
  1104. if (MiIsPteOnPdeBoundary (PointerPte)) {
  1105. PointerPde += 1;
  1106. if (MiIsPteOnPdeBoundary (PointerPde)) {
  1107. StartPpe += 1;
  1108. }
  1109. }
  1110. }
  1111. //
  1112. // Adjust the free descriptor for all the pages we just took.
  1113. //
  1114. MiFreeDescriptor->PageCount -= (FreeNextPhysicalPage - MiFreeDescriptor->BasePage);
  1115. MiFreeDescriptor->BasePage = FreeNextPhysicalPage;
  1116. }
  1117. //
  1118. // Non-paged pages now exist, build the pool structures.
  1119. //
  1120. // Before nonpaged pool can be used, the PFN database must
  1121. // be built. This is due to the fact that the start and end of
  1122. // allocation bits for nonpaged pool are maintained in the
  1123. // PFN elements for the corresponding pages.
  1124. //
  1125. MiInitializeNonPagedPool ();
  1126. MiInitializeNonPagedPoolThresholds ();
  1127. if (MiInitialLargePage != (PFN_NUMBER) -1) {
  1128. //
  1129. // Add the initial large page range to the translation register list.
  1130. //
  1131. MiAddTrEntry ((ULONG_PTR)MmPfnDatabase,
  1132. (ULONG_PTR)MmPfnDatabase + (MiInitialLargePageSize << PAGE_SHIFT));
  1133. MiAddCachedRange (MiInitialLargePage,
  1134. MiInitialLargePage + MiInitialLargePageSize - 1);
  1135. }
  1136. MmFreePagesByColor[1] = &MmFreePagesByColor[0][MmSecondaryColors];
  1137. //
  1138. // Initialize support for colored pages.
  1139. //
  1140. for (i = 0; i < MmSecondaryColors; i += 1) {
  1141. MmFreePagesByColor[ZeroedPageList][i].Flink = MM_EMPTY_LIST;
  1142. MmFreePagesByColor[ZeroedPageList][i].Blink = (PVOID) MM_EMPTY_LIST;
  1143. MmFreePagesByColor[ZeroedPageList][i].Count = 0;
  1144. MmFreePagesByColor[FreePageList][i].Flink = MM_EMPTY_LIST;
  1145. MmFreePagesByColor[FreePageList][i].Blink = (PVOID) MM_EMPTY_LIST;
  1146. MmFreePagesByColor[FreePageList][i].Count = 0;
  1147. }
  1148. #if MM_MAXIMUM_NUMBER_OF_COLORS > 1
  1149. for (i = 0; i < MM_MAXIMUM_NUMBER_OF_COLORS; i += 1) {
  1150. MmFreePagesByPrimaryColor[ZeroedPageList][i].ListName = ZeroedPageList;
  1151. MmFreePagesByPrimaryColor[FreePageList][i].ListName = FreePageList;
  1152. MmFreePagesByPrimaryColor[ZeroedPageList][i].Flink = MM_EMPTY_LIST;
  1153. MmFreePagesByPrimaryColor[FreePageList][i].Flink = MM_EMPTY_LIST;
  1154. MmFreePagesByPrimaryColor[ZeroedPageList][i].Blink = MM_EMPTY_LIST;
  1155. MmFreePagesByPrimaryColor[FreePageList][i].Blink = MM_EMPTY_LIST;
  1156. }
  1157. #endif
  1158. //
  1159. // Go through the page table entries for hyper space and for any page
  1160. // which is valid, update the corresponding PFN database element.
  1161. //
  1162. StartPde = MiGetPdeAddress (HYPER_SPACE);
  1163. StartPpe = MiGetPpeAddress (HYPER_SPACE);
  1164. EndPde = MiGetPdeAddress(HYPER_SPACE_END);
  1165. if (StartPpe->u.Hard.Valid == 0) {
  1166. First = TRUE;
  1167. PdePage = 0;
  1168. Pfn1 = NULL;
  1169. }
  1170. else {
  1171. First = FALSE;
  1172. PdePage = MI_GET_PAGE_FRAME_FROM_PTE (StartPpe);
  1173. if (MiIsRegularMemory (LoaderBlock, PdePage)) {
  1174. Pfn1 = MI_PFN_ELEMENT(PdePage);
  1175. }
  1176. else {
  1177. Pfn1 = NULL;
  1178. }
  1179. }
  1180. while (StartPde <= EndPde) {
  1181. if (First == TRUE || MiIsPteOnPdeBoundary(StartPde)) {
  1182. First = FALSE;
  1183. StartPpe = MiGetPteAddress(StartPde);
  1184. if (StartPpe->u.Hard.Valid == 0) {
  1185. StartPpe += 1;
  1186. StartPde = MiGetVirtualAddressMappedByPte (StartPpe);
  1187. continue;
  1188. }
  1189. PdePage = MI_GET_PAGE_FRAME_FROM_PTE(StartPpe);
  1190. if (MiIsRegularMemory (LoaderBlock, PdePage)) {
  1191. Pfn1 = MI_PFN_ELEMENT(PdePage);
  1192. Pfn1->u4.PteFrame = MmSystemParentTablePage;
  1193. Pfn1->PteAddress = StartPde;
  1194. Pfn1->u2.ShareCount += 1;
  1195. Pfn1->u3.e2.ReferenceCount = 1;
  1196. Pfn1->u3.e1.PageLocation = ActiveAndValid;
  1197. Pfn1->u3.e1.CacheAttribute = MiCached;
  1198. Pfn1->u3.e1.PageColor =
  1199. MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE(StartPpe));
  1200. }
  1201. }
  1202. if (StartPde->u.Hard.Valid == 1) {
  1203. PdePage = MI_GET_PAGE_FRAME_FROM_PTE(StartPde);
  1204. PointerPde = MiGetPteAddress(StartPde);
  1205. Pfn2 = MI_PFN_ELEMENT(PdePage);
  1206. if (MiIsRegularMemory (LoaderBlock, PdePage)) {
  1207. Pfn2->u4.PteFrame = MI_GET_PAGE_FRAME_FROM_PTE(PointerPde);
  1208. ASSERT (MiIsRegularMemory (LoaderBlock, Pfn2->u4.PteFrame));
  1209. Pfn2->PteAddress = StartPde;
  1210. Pfn2->u2.ShareCount += 1;
  1211. Pfn2->u3.e2.ReferenceCount = 1;
  1212. Pfn2->u3.e1.PageLocation = ActiveAndValid;
  1213. Pfn2->u3.e1.CacheAttribute = MiCached;
  1214. Pfn2->u3.e1.PageColor =
  1215. MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE (StartPde));
  1216. }
  1217. PointerPte = MiGetVirtualAddressMappedByPte(StartPde);
  1218. for (j = 0 ; j < PTE_PER_PAGE; j += 1) {
  1219. if (PointerPte->u.Hard.Valid == 1) {
  1220. ASSERT (MiIsRegularMemory (LoaderBlock, PdePage));
  1221. Pfn2->u2.ShareCount += 1;
  1222. if (MiIsRegularMemory (LoaderBlock, PointerPte->u.Hard.PageFrameNumber)) {
  1223. Pfn3 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
  1224. Pfn3->u4.PteFrame = PdePage;
  1225. Pfn3->PteAddress = PointerPte;
  1226. Pfn3->u2.ShareCount += 1;
  1227. Pfn3->u3.e2.ReferenceCount = 1;
  1228. Pfn3->u3.e1.PageLocation = ActiveAndValid;
  1229. Pfn3->u3.e1.CacheAttribute = MiCached;
  1230. Pfn3->u3.e1.PageColor =
  1231. MI_GET_COLOR_FROM_SECONDARY(
  1232. MI_GET_PAGE_COLOR_FROM_PTE (
  1233. PointerPte));
  1234. }
  1235. }
  1236. PointerPte += 1;
  1237. }
  1238. }
  1239. StartPde += 1;
  1240. }
  1241. //
  1242. // Go through the page table entries for kernel space and for any page
  1243. // which is valid, update the corresponding PFN database element.
  1244. //
  1245. StartPde = MiGetPdeAddress ((PVOID)KADDRESS_BASE);
  1246. StartPpe = MiGetPpeAddress ((PVOID)KADDRESS_BASE);
  1247. EndPde = MiGetPdeAddress((PVOID)MM_SYSTEM_SPACE_END);
  1248. if (StartPpe->u.Hard.Valid == 0) {
  1249. First = TRUE;
  1250. PpePage = 0;
  1251. Pfn1 = NULL;
  1252. }
  1253. else {
  1254. First = FALSE;
  1255. PpePage = MI_GET_PAGE_FRAME_FROM_PTE (StartPpe);
  1256. if (MiIsRegularMemory (LoaderBlock, PpePage)) {
  1257. Pfn1 = MI_PFN_ELEMENT(PpePage);
  1258. }
  1259. else {
  1260. Pfn1 = NULL;
  1261. }
  1262. }
  1263. while (StartPde <= EndPde) {
  1264. if (First == TRUE || MiIsPteOnPdeBoundary(StartPde)) {
  1265. First = FALSE;
  1266. StartPpe = MiGetPteAddress(StartPde);
  1267. if (StartPpe->u.Hard.Valid == 0) {
  1268. StartPpe += 1;
  1269. StartPde = MiGetVirtualAddressMappedByPte (StartPpe);
  1270. continue;
  1271. }
  1272. PpePage = MI_GET_PAGE_FRAME_FROM_PTE(StartPpe);
  1273. if (MiIsRegularMemory (LoaderBlock, PpePage)) {
  1274. Pfn1 = MI_PFN_ELEMENT(PpePage);
  1275. Pfn1->u4.PteFrame = MmSystemParentTablePage;
  1276. Pfn1->PteAddress = StartPpe;
  1277. Pfn1->u2.ShareCount += 1;
  1278. Pfn1->u3.e2.ReferenceCount = 1;
  1279. Pfn1->u3.e1.PageLocation = ActiveAndValid;
  1280. Pfn1->u3.e1.CacheAttribute = MiCached;
  1281. Pfn1->u3.e1.PageColor =
  1282. MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE(StartPpe));
  1283. }
  1284. else {
  1285. Pfn1 = NULL;
  1286. }
  1287. }
  1288. if (StartPde->u.Hard.Valid == 1) {
  1289. if (MI_PDE_MAPS_LARGE_PAGE (StartPde)) {
  1290. PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (StartPde);
  1291. ASSERT (Pfn1 != NULL);
  1292. Pfn1->u2.ShareCount += PTE_PER_PAGE;
  1293. for (j = 0 ; j < PTE_PER_PAGE; j += 1) {
  1294. if (MiIsRegularMemory (LoaderBlock, PageFrameIndex + j)) {
  1295. Pfn3 = MI_PFN_ELEMENT (PageFrameIndex + j);
  1296. Pfn3->u4.PteFrame = PpePage;
  1297. Pfn3->PteAddress = StartPde;
  1298. Pfn3->u2.ShareCount += 1;
  1299. Pfn3->u3.e2.ReferenceCount = 1;
  1300. Pfn3->u3.e1.PageLocation = ActiveAndValid;
  1301. Pfn3->u3.e1.CacheAttribute = MiCached;
  1302. Pfn3->u3.e1.PageColor =
  1303. MI_GET_COLOR_FROM_SECONDARY(
  1304. MI_GET_PAGE_COLOR_FROM_PTE (
  1305. StartPde));
  1306. }
  1307. }
  1308. }
  1309. else {
  1310. PdePage = MI_GET_PAGE_FRAME_FROM_PTE(StartPde);
  1311. if (MiIsRegularMemory (LoaderBlock, PdePage)) {
  1312. Pfn2 = MI_PFN_ELEMENT(PdePage);
  1313. Pfn2->u4.PteFrame = PpePage;
  1314. Pfn2->PteAddress = StartPde;
  1315. Pfn2->u2.ShareCount += 1;
  1316. Pfn2->u3.e2.ReferenceCount = 1;
  1317. Pfn2->u3.e1.PageLocation = ActiveAndValid;
  1318. Pfn2->u3.e1.CacheAttribute = MiCached;
  1319. Pfn2->u3.e1.PageColor =
  1320. MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE (StartPde));
  1321. }
  1322. else {
  1323. Pfn2 = NULL;
  1324. }
  1325. PointerPte = MiGetVirtualAddressMappedByPte(StartPde);
  1326. for (j = 0 ; j < PTE_PER_PAGE; j += 1) {
  1327. if (PointerPte->u.Hard.Valid == 1) {
  1328. ASSERT (Pfn2 != NULL);
  1329. Pfn2->u2.ShareCount += 1;
  1330. if (MiIsRegularMemory (LoaderBlock, PointerPte->u.Hard.PageFrameNumber)) {
  1331. Pfn3 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
  1332. Pfn3->u4.PteFrame = PdePage;
  1333. Pfn3->PteAddress = PointerPte;
  1334. Pfn3->u2.ShareCount += 1;
  1335. Pfn3->u3.e2.ReferenceCount = 1;
  1336. Pfn3->u3.e1.PageLocation = ActiveAndValid;
  1337. Pfn3->u3.e1.CacheAttribute = MiCached;
  1338. Pfn3->u3.e1.PageColor =
  1339. MI_GET_COLOR_FROM_SECONDARY(
  1340. MI_GET_PAGE_COLOR_FROM_PTE (
  1341. PointerPte));
  1342. }
  1343. }
  1344. PointerPte += 1;
  1345. }
  1346. }
  1347. }
  1348. StartPde += 1;
  1349. }
  1350. //
  1351. // Mark the system top level page directory parent page as in use.
  1352. //
  1353. PointerPte = MiGetPteAddress((PVOID)PDE_KTBASE);
  1354. Pfn2 = MI_PFN_ELEMENT(MmSystemParentTablePage);
  1355. Pfn2->u4.PteFrame = MmSystemParentTablePage;
  1356. Pfn2->PteAddress = PointerPte;
  1357. Pfn2->u1.Event = (PVOID) CurrentProcess;
  1358. Pfn2->u2.ShareCount += 1;
  1359. Pfn2->u3.e2.ReferenceCount = 1;
  1360. Pfn2->u3.e1.PageLocation = ActiveAndValid;
  1361. Pfn2->u3.e1.CacheAttribute = MiCached;
  1362. Pfn2->u3.e1.PageColor =
  1363. MI_GET_COLOR_FROM_SECONDARY(MI_GET_PAGE_COLOR_FROM_PTE (PointerPte));
  1364. //
  1365. // Temporarily mark the user top level page directory parent page as in use
  1366. // so this page will not be put in the free list.
  1367. //
  1368. PointerPte = MiGetPteAddress((PVOID)PDE_UTBASE);
  1369. Pfn2 = MI_PFN_ELEMENT(PointerPte->u.Hard.PageFrameNumber);
  1370. Pfn2->u4.PteFrame = PointerPte->u.Hard.PageFrameNumber;
  1371. Pfn2->PteAddress = PointerPte;
  1372. Pfn2->u1.Event = NULL;
  1373. Pfn2->u2.ShareCount += 1;
  1374. Pfn2->u3.e2.ReferenceCount = 1;
  1375. Pfn2->u3.e1.PageLocation = ActiveAndValid;
  1376. Pfn2->u3.e1.CacheAttribute = MiCached;
  1377. Pfn2->u3.e1.PageColor =
  1378. MI_GET_COLOR_FROM_SECONDARY(MI_GET_PAGE_COLOR_FROM_PTE (PointerPte));
  1379. //
  1380. // Mark the region 1 session top level page directory parent page as in use.
  1381. // This page will never be freed.
  1382. //
  1383. PointerPte = MiGetPteAddress((PVOID)PDE_STBASE);
  1384. Pfn2 = MI_PFN_ELEMENT(MmSessionParentTablePage);
  1385. Pfn2->u4.PteFrame = MmSessionParentTablePage;
  1386. Pfn2->PteAddress = PointerPte;
  1387. Pfn2->u2.ShareCount += 1;
  1388. Pfn2->u3.e2.ReferenceCount = 1;
  1389. Pfn2->u3.e1.PageLocation = ActiveAndValid;
  1390. Pfn2->u3.e1.CacheAttribute = MiCached;
  1391. Pfn2->u3.e1.PageColor =
  1392. MI_GET_COLOR_FROM_SECONDARY(MI_GET_PAGE_COLOR_FROM_PTE (PointerPte));
  1393. //
  1394. // Mark the default PPE table page as in use so that this page will never
  1395. // be used.
  1396. //
  1397. PageFrameIndex = MiDefaultPpe.u.Hard.PageFrameNumber;
  1398. PointerPte = KSEG_ADDRESS(PageFrameIndex);
  1399. Pfn2 = MI_PFN_ELEMENT(PageFrameIndex);
  1400. Pfn2->u4.PteFrame = PageFrameIndex;
  1401. Pfn2->PteAddress = PointerPte;
  1402. Pfn2->u1.Event = (PVOID) CurrentProcess;
  1403. Pfn2->u2.ShareCount += 1;
  1404. Pfn2->u3.e2.ReferenceCount = 1;
  1405. Pfn2->u3.e1.PageLocation = ActiveAndValid;
  1406. Pfn2->u3.e1.CacheAttribute = MiCached;
  1407. Pfn2->u3.e1.PageColor =
  1408. MI_GET_COLOR_FROM_SECONDARY(MI_GET_PAGE_COLOR_FROM_PTE (PointerPte));
  1409. //
  1410. // If page zero is still unused, mark it as in use. This is
  1411. // because we want to find bugs where a physical page
  1412. // is specified as zero.
  1413. //
  1414. Pfn1 = &MmPfnDatabase[MmLowestPhysicalPage];
  1415. if (Pfn1->u3.e2.ReferenceCount == 0) {
  1416. //
  1417. // Make the reference count non-zero and point it into a
  1418. // page directory.
  1419. //
  1420. Pde = MiGetPdeAddress ((PVOID)(KADDRESS_BASE + 0xb0000000));
  1421. PdePage = MI_GET_PAGE_FRAME_FROM_PTE(Pde);
  1422. Pfn1->u4.PteFrame = PdePageNumber;
  1423. Pfn1->PteAddress = Pde;
  1424. Pfn1->u2.ShareCount += 1;
  1425. Pfn1->u3.e2.ReferenceCount = 1;
  1426. Pfn1->u3.e1.PageLocation = ActiveAndValid;
  1427. Pfn1->u3.e1.CacheAttribute = MiCached;
  1428. Pfn1->u3.e1.PageColor = MI_GET_COLOR_FROM_SECONDARY(
  1429. MI_GET_PAGE_COLOR_FROM_PTE (Pde));
  1430. }
  1431. //
  1432. // Walk through the memory descriptors and add pages to the
  1433. // free list in the PFN database.
  1434. //
  1435. NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
  1436. while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
  1437. MemoryDescriptor = CONTAINING_RECORD(NextMd,
  1438. MEMORY_ALLOCATION_DESCRIPTOR,
  1439. ListEntry);
  1440. i = MemoryDescriptor->PageCount;
  1441. NextPhysicalPage = MemoryDescriptor->BasePage;
  1442. switch (MemoryDescriptor->MemoryType) {
  1443. case LoaderBad:
  1444. if (NextPhysicalPage > MmHighestPhysicalPage) {
  1445. i = 0;
  1446. }
  1447. else if (NextPhysicalPage + i > MmHighestPhysicalPage + 1) {
  1448. i = MmHighestPhysicalPage + 1 - NextPhysicalPage;
  1449. }
  1450. while (i != 0) {
  1451. MiInsertPageInList (&MmBadPageListHead, NextPhysicalPage);
  1452. i -= 1;
  1453. NextPhysicalPage += 1;
  1454. }
  1455. break;
  1456. case LoaderFree:
  1457. case LoaderLoadedProgram:
  1458. case LoaderFirmwareTemporary:
  1459. case LoaderOsloaderStack:
  1460. Pfn1 = MI_PFN_ELEMENT (NextPhysicalPage);
  1461. while (i != 0) {
  1462. if (Pfn1->u3.e2.ReferenceCount == 0) {
  1463. //
  1464. // Set the PTE address to the physical page for
  1465. // virtual address alignment checking.
  1466. //
  1467. Pfn1->PteAddress = KSEG_ADDRESS (NextPhysicalPage);
  1468. Pfn1->u3.e1.CacheAttribute = MiCached;
  1469. MiDetermineNode(NextPhysicalPage, Pfn1);
  1470. MiInsertPageInFreeList (NextPhysicalPage);
  1471. }
  1472. Pfn1 += 1;
  1473. i -= 1;
  1474. NextPhysicalPage += 1;
  1475. }
  1476. break;
  1477. case LoaderSpecialMemory:
  1478. case LoaderBBTMemory:
  1479. case LoaderFirmwarePermanent:
  1480. //
  1481. // Skip this range.
  1482. //
  1483. break;
  1484. default:
  1485. PointerPte = KSEG_ADDRESS(NextPhysicalPage);
  1486. Pfn1 = MI_PFN_ELEMENT (NextPhysicalPage);
  1487. while (i != 0) {
  1488. //
  1489. // Set page as in use.
  1490. //
  1491. if (Pfn1->u3.e2.ReferenceCount == 0) {
  1492. Pfn1->u4.PteFrame = PdePageNumber;
  1493. Pfn1->PteAddress = PointerPte;
  1494. Pfn1->u2.ShareCount += 1;
  1495. Pfn1->u3.e2.ReferenceCount = 1;
  1496. Pfn1->u3.e1.PageLocation = ActiveAndValid;
  1497. Pfn1->u3.e1.CacheAttribute = MiCached;
  1498. Pfn1->u3.e1.PageColor = MI_GET_COLOR_FROM_SECONDARY(
  1499. MI_GET_PAGE_COLOR_FROM_PTE (
  1500. PointerPte));
  1501. if (MemoryDescriptor->MemoryType == LoaderXIPRom) {
  1502. Pfn1->u1.Flink = 0;
  1503. Pfn1->u2.ShareCount = 0;
  1504. Pfn1->u3.e2.ReferenceCount = 0;
  1505. Pfn1->u3.e1.PageLocation = 0;
  1506. Pfn1->u3.e1.Rom = 1;
  1507. Pfn1->u4.InPageError = 0;
  1508. Pfn1->u3.e1.PrototypePte = 1;
  1509. }
  1510. }
  1511. Pfn1 += 1;
  1512. i -= 1;
  1513. NextPhysicalPage += 1;
  1514. PointerPte += 1;
  1515. }
  1516. break;
  1517. }
  1518. NextMd = MemoryDescriptor->ListEntry.Flink;
  1519. }
  1520. //
  1521. // If the large page chunk came from the middle of the free descriptor (due
  1522. // to alignment requirements), then add the pages from the split bottom
  1523. // portion of the free descriptor now.
  1524. //
  1525. i = MiSlushDescriptorCount;
  1526. NextPhysicalPage = MiSlushDescriptorBase;
  1527. Pfn1 = MI_PFN_ELEMENT (NextPhysicalPage);
  1528. while (i != 0) {
  1529. if (Pfn1->u3.e2.ReferenceCount == 0) {
  1530. //
  1531. // Set the PTE address to the physical page for
  1532. // virtual address alignment checking.
  1533. //
  1534. Pfn1->PteAddress = KSEG_ADDRESS (NextPhysicalPage);
  1535. Pfn1->u3.e1.CacheAttribute = MiCached;
  1536. MiDetermineNode(NextPhysicalPage, Pfn1);
  1537. MiInsertPageInFreeList (NextPhysicalPage);
  1538. }
  1539. Pfn1 += 1;
  1540. i -= 1;
  1541. NextPhysicalPage += 1;
  1542. }
  1543. //
  1544. // Mark all PFN entries for the PFN pages in use.
  1545. //
  1546. if (MiInitialLargePage != (PFN_NUMBER) -1) {
  1547. //
  1548. // The PFN database is allocated in large pages.
  1549. //
  1550. PfnAllocation = MxPfnAllocation;
  1551. PageFrameIndex = MI_CONVERT_PHYSICAL_TO_PFN (MmPfnDatabase);
  1552. Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
  1553. do {
  1554. Pfn1->PteAddress = KSEG_ADDRESS(PageFrameIndex);
  1555. Pfn1->u3.e1.PageColor = 0;
  1556. Pfn1->u3.e2.ReferenceCount = 1;
  1557. Pfn1->u3.e1.PageLocation = ActiveAndValid;
  1558. Pfn1->u3.e1.CacheAttribute = MiCached;
  1559. PageFrameIndex += 1;
  1560. Pfn1 += 1;
  1561. PfnAllocation -= 1;
  1562. } while (PfnAllocation != 0);
  1563. if (MmDynamicPfn == 0) {
  1564. //
  1565. // Scan the PFN database backward for pages that are completely
  1566. // zero. These pages are unused and can be added to the free list.
  1567. //
  1568. // This allows machines with sparse physical memory to have a
  1569. // minimal PFN database even when mapped with large pages.
  1570. //
  1571. BottomPfn = MI_PFN_ELEMENT (MmHighestPhysicalPage);
  1572. do {
  1573. //
  1574. // Compute the address of the start of the page that is next
  1575. // lower in memory and scan backwards until that page address
  1576. // is reached or just crossed.
  1577. //
  1578. if (((ULONG_PTR)BottomPfn & (PAGE_SIZE - 1)) != 0) {
  1579. BasePfn = (PMMPFN)((ULONG_PTR)BottomPfn & ~(PAGE_SIZE - 1));
  1580. TopPfn = BottomPfn + 1;
  1581. }
  1582. else {
  1583. BasePfn = (PMMPFN)((ULONG_PTR)BottomPfn - PAGE_SIZE);
  1584. TopPfn = BottomPfn;
  1585. }
  1586. while (BottomPfn > BasePfn) {
  1587. BottomPfn -= 1;
  1588. }
  1589. //
  1590. // If the entire range over which the PFN entries span is
  1591. // completely zero and the PFN entry that maps the page is
  1592. // not in the range, then add the page to the appropriate
  1593. // free list.
  1594. //
  1595. Range = (ULONG_PTR)TopPfn - (ULONG_PTR)BottomPfn;
  1596. if (RtlCompareMemoryUlong((PVOID)BottomPfn, Range, 0) == Range) {
  1597. //
  1598. // Set the PTE address to the physical page for virtual
  1599. // address alignment checking.
  1600. //
  1601. PageFrameIndex = MI_CONVERT_PHYSICAL_TO_PFN (BasePfn);
  1602. Pfn1 = MI_PFN_ELEMENT(PageFrameIndex);
  1603. ASSERT (Pfn1->u3.e2.ReferenceCount == 1);
  1604. ASSERT (Pfn1->PteAddress == KSEG_ADDRESS(PageFrameIndex));
  1605. Pfn1->u3.e2.ReferenceCount = 0;
  1606. Pfn1->PteAddress = (PMMPTE)((ULONG_PTR)PageFrameIndex << PTE_SHIFT);
  1607. Pfn1->u3.e1.PageColor = 0;
  1608. MiInsertPageInFreeList (PageFrameIndex);
  1609. }
  1610. } while (BottomPfn > MmPfnDatabase);
  1611. }
  1612. }
  1613. else {
  1614. //
  1615. // The PFN database is sparsely allocated in small pages.
  1616. //
  1617. PointerPte = MiGetPteAddress (MmPfnDatabase);
  1618. LastPte = MiGetPteAddress (MmPfnDatabase + MmHighestPhysicalPage + 1);
  1619. if (LastPte != PAGE_ALIGN (LastPte)) {
  1620. LastPte += 1;
  1621. }
  1622. StartPpe = MiGetPdeAddress (PointerPte);
  1623. PointerPde = MiGetPteAddress (PointerPte);
  1624. while (PointerPte < LastPte) {
  1625. if (StartPpe->u.Hard.Valid == 0) {
  1626. StartPpe += 1;
  1627. PointerPde = MiGetVirtualAddressMappedByPte (StartPpe);
  1628. PointerPte = MiGetVirtualAddressMappedByPte (PointerPde);
  1629. continue;
  1630. }
  1631. if (PointerPde->u.Hard.Valid == 0) {
  1632. PointerPde += 1;
  1633. PointerPte = MiGetVirtualAddressMappedByPte (PointerPde);
  1634. if (MiIsPteOnPdeBoundary (PointerPde)) {
  1635. StartPpe += 1;
  1636. }
  1637. continue;
  1638. }
  1639. if (PointerPte->u.Hard.Valid == 1) {
  1640. PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
  1641. Pfn1 = MI_PFN_ELEMENT (PageFrameIndex);
  1642. Pfn1->PteAddress = PointerPte;
  1643. Pfn1->u3.e1.PageColor = 0;
  1644. Pfn1->u3.e2.ReferenceCount = 1;
  1645. Pfn1->u3.e1.PageLocation = ActiveAndValid;
  1646. Pfn1->u3.e1.CacheAttribute = MiCached;
  1647. }
  1648. PointerPte += 1;
  1649. if (MiIsPteOnPdeBoundary (PointerPte)) {
  1650. PointerPde += 1;
  1651. if (MiIsPteOnPdeBoundary (PointerPde)) {
  1652. StartPpe += 1;
  1653. }
  1654. }
  1655. }
  1656. }
  1657. //
  1658. // Initialize the nonpaged pool.
  1659. //
  1660. InitializePool (NonPagedPool, 0);
  1661. //
  1662. // Initialize the nonpaged available PTEs for mapping I/O space
  1663. // and kernel stacks.
  1664. //
  1665. PointerPte = MiGetPteAddress (SystemPteStart);
  1666. ASSERT (((ULONG_PTR)PointerPte & (PAGE_SIZE - 1)) == 0);
  1667. MmNumberOfSystemPtes = (ULONG)(MiGetPteAddress(MmPfnDatabase) - PointerPte - 1);
  1668. MiInitializeSystemPtes (PointerPte, MmNumberOfSystemPtes, SystemPteSpace);
  1669. //
  1670. // Initialize memory management structures for the system process.
  1671. //
  1672. // Set the address of the first and last reserved PTE in hyper space.
  1673. //
  1674. MmFirstReservedMappingPte = MiGetPteAddress (FIRST_MAPPING_PTE);
  1675. MmLastReservedMappingPte = MiGetPteAddress (LAST_MAPPING_PTE);
  1676. //
  1677. // Create zeroing PTEs for the zero page thread.
  1678. //
  1679. MiFirstReservedZeroingPte = MiReserveSystemPtes (NUMBER_OF_ZEROING_PTES + 1,
  1680. SystemPteSpace);
  1681. RtlZeroMemory (MiFirstReservedZeroingPte,
  1682. (NUMBER_OF_ZEROING_PTES + 1) * sizeof(MMPTE));
  1683. //
  1684. // Use the page frame number field of the first PTE as an
  1685. // offset into the available zeroing PTEs.
  1686. //
  1687. MiFirstReservedZeroingPte->u.Hard.PageFrameNumber = NUMBER_OF_ZEROING_PTES;
  1688. //
  1689. // Create the VAD bitmap for this process.
  1690. //
  1691. PointerPte = MiGetPteAddress (VAD_BITMAP_SPACE);
  1692. PageFrameIndex = MiRemoveAnyPage (0);
  1693. //
  1694. // Note the global bit must be off for the bitmap data.
  1695. //
  1696. TempPte = ValidPdePde;
  1697. TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
  1698. MI_WRITE_VALID_PTE (PointerPte, TempPte);
  1699. //
  1700. // Point to the page we just created and zero it.
  1701. //
  1702. RtlZeroMemory (VAD_BITMAP_SPACE, PAGE_SIZE);
  1703. MiLastVadBit = (ULONG)((((ULONG_PTR) MI_64K_ALIGN (MM_HIGHEST_VAD_ADDRESS))) / X64K);
  1704. if (MiLastVadBit > PAGE_SIZE * 8 - 1) {
  1705. MiLastVadBit = PAGE_SIZE * 8 - 1;
  1706. }
  1707. //
  1708. // The PFN element for the page directory parent will be initialized
  1709. // a second time when the process address space is initialized. Therefore,
  1710. // the share count and the reference count must be set to zero.
  1711. //
  1712. Pfn1 = MI_PFN_ELEMENT(MI_GET_PAGE_FRAME_FROM_PTE((PMMPTE)PDE_SELFMAP));
  1713. Pfn1->u2.ShareCount = 0;
  1714. Pfn1->u3.e2.ReferenceCount = 0;
  1715. //
  1716. // The PFN element for the hyper space page directory page will be
  1717. // initialized a second time when the process address space is initialized.
  1718. // Therefore, the share count and the reference count must be set to zero.
  1719. //
  1720. PointerPte = MiGetPpeAddress(HYPER_SPACE);
  1721. Pfn1 = MI_PFN_ELEMENT(MI_GET_PAGE_FRAME_FROM_PTE(PointerPte));
  1722. Pfn1->u2.ShareCount = 0;
  1723. Pfn1->u3.e2.ReferenceCount = 0;
  1724. //
  1725. // The PFN elements for the hyper space page table page and working set list
  1726. // page will be initialized a second time when the process address space
  1727. // is initialized. Therefore, the share count and the reference must be
  1728. // set to zero.
  1729. //
  1730. StartPde = MiGetPdeAddress(HYPER_SPACE);
  1731. Pfn1 = MI_PFN_ELEMENT(MI_GET_PAGE_FRAME_FROM_PTE(StartPde));
  1732. Pfn1->u2.ShareCount = 0;
  1733. Pfn1->u3.e2.ReferenceCount = 0;
  1734. KeInitializeEvent (&MiImageMappingPteEvent,
  1735. NotificationEvent,
  1736. FALSE);
  1737. //
  1738. // Initialize this process's memory management structures including
  1739. // the working set list.
  1740. //
  1741. //
  1742. // The PFN element for the page directory has already been initialized,
  1743. // zero the reference count and the share count so they won't be
  1744. // wrong.
  1745. //
  1746. Pfn1 = MI_PFN_ELEMENT (PdePageNumber);
  1747. Pfn1->u2.ShareCount = 0;
  1748. Pfn1->u3.e2.ReferenceCount = 0;
  1749. //
  1750. // Get a page for the working set list and map it into the page
  1751. // directory at the page after hyperspace.
  1752. //
  1753. PageFrameIndex = MiRemoveAnyPage (0);
  1754. CurrentProcess->WorkingSetPage = PageFrameIndex;
  1755. TempPte = ValidPdePde;
  1756. TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
  1757. PointerPte = MiGetPteAddress (MmWorkingSetList);
  1758. MI_WRITE_VALID_PTE (PointerPte, TempPte);
  1759. RtlZeroMemory (KSEG_ADDRESS(PageFrameIndex), PAGE_SIZE);
  1760. CurrentProcess->Vm.MaximumWorkingSetSize = (ULONG)MmSystemProcessWorkingSetMax;
  1761. CurrentProcess->Vm.MinimumWorkingSetSize = (ULONG)MmSystemProcessWorkingSetMin;
  1762. MmSessionMapInfo.RegionId = START_SESSION_RID;
  1763. MmSessionMapInfo.SequenceNumber = START_SEQUENCE;
  1764. KeAttachSessionSpace (&MmSessionMapInfo, MmSessionParentTablePage);
  1765. MmInitializeProcessAddressSpace (CurrentProcess, NULL, NULL, NULL);
  1766. KeFlushCurrentTb ();
  1767. #if defined (_MI_DEBUG_ALTPTE)
  1768. MmDebug |= MM_DBG_STOP_ON_WOW64_ACCVIO;
  1769. #endif
  1770. //
  1771. // Restore the loader block memory descriptor to its original contents
  1772. // as our caller relies on it.
  1773. //
  1774. MiFreeDescriptor->BasePage = (ULONG) MiOldFreeDescriptorBase;
  1775. MiFreeDescriptor->PageCount = (ULONG) MiOldFreeDescriptorCount;
  1776. return;
  1777. }
  1778. VOID
  1779. MiSweepCacheMachineDependent (
  1780. IN PVOID VirtualAddress,
  1781. IN SIZE_T Size,
  1782. IN ULONG InputAttribute
  1783. )
  1784. /*++
  1785. Routine Description:
  1786. This function checks and performs appropriate cache flushing operations.
  1787. Arguments:
  1788. StartVirtual - Supplies the start address of the region of pages.
  1789. Size - Supplies the size of the region in pages.
  1790. CacheAttribute - Supplies the new cache attribute.
  1791. Return Value:
  1792. None.
  1793. --*/
  1794. {
  1795. SIZE_T Size2;
  1796. PFN_NUMBER i;
  1797. PFN_NUMBER PageFrameIndex;
  1798. PFN_NUMBER NumberOfPages;
  1799. PVOID BaseAddress;
  1800. PVOID Va;
  1801. PMMPTE PointerPde;
  1802. PMMPTE PointerPte;
  1803. PMMPTE EndPte;
  1804. MMPTE TempPte;
  1805. MI_PFN_CACHE_ATTRIBUTE CacheAttribute;
  1806. MMPTE_FLUSH_LIST PteFlushList;
  1807. CacheAttribute = (MI_PFN_CACHE_ATTRIBUTE) InputAttribute;
  1808. NumberOfPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES (VirtualAddress, Size);
  1809. VirtualAddress = PAGE_ALIGN(VirtualAddress);
  1810. Size = NumberOfPages * PAGE_SIZE;
  1811. //
  1812. // Unfortunately some IA64 machines have hardware problems when sweeping
  1813. // address ranges that are backed by I/O space instead of system DRAM.
  1814. //
  1815. // So we have to check for that here and chop up the request if need be
  1816. // so that only system DRAM addresses get swept.
  1817. //
  1818. i = 0;
  1819. Size2 = 0;
  1820. BaseAddress = NULL;
  1821. PointerPte = MiGetPteAddress (VirtualAddress);
  1822. EndPte = PointerPte + NumberOfPages;
  1823. PointerPde = MiGetPdeAddress (VirtualAddress);
  1824. for (i = 0; i < NumberOfPages; ) {
  1825. if (MI_PDE_MAPS_LARGE_PAGE (PointerPde)) {
  1826. Va = MiGetVirtualAddressMappedByPde (PointerPde);
  1827. ASSERT (MiGetPteOffset (Va) == 0);
  1828. PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPde);
  1829. }
  1830. else {
  1831. PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
  1832. }
  1833. if (!MI_IS_PFN (PageFrameIndex)) {
  1834. //
  1835. // Sweep the partial range if one exists.
  1836. //
  1837. if (Size2 != 0) {
  1838. KeSweepCacheRangeWithDrain (TRUE, BaseAddress, (ULONG)Size2);
  1839. Size2 = 0;
  1840. }
  1841. }
  1842. else {
  1843. if (Size2 == 0) {
  1844. BaseAddress = (PVOID)((PCHAR)VirtualAddress + i * PAGE_SIZE);
  1845. }
  1846. if (MI_PDE_MAPS_LARGE_PAGE (PointerPde)) {
  1847. Size2 += PTE_PER_PAGE * PAGE_SIZE;
  1848. }
  1849. else {
  1850. Size2 += PAGE_SIZE;
  1851. }
  1852. }
  1853. if (MI_PDE_MAPS_LARGE_PAGE (PointerPde)) {
  1854. i += PTE_PER_PAGE;
  1855. PointerPte += PTE_PER_PAGE;
  1856. PointerPde += 1;
  1857. }
  1858. else {
  1859. i += 1;
  1860. PointerPte += 1;
  1861. if (MiIsPteOnPdeBoundary (PointerPte)) {
  1862. PointerPde += 1;
  1863. }
  1864. }
  1865. }
  1866. //
  1867. // Sweep any remainder.
  1868. //
  1869. if (Size2 != 0) {
  1870. KeSweepCacheRangeWithDrain (TRUE, BaseAddress, (ULONG)Size2);
  1871. }
  1872. PointerPde = MiGetPdeAddress (VirtualAddress);
  1873. if ((CacheAttribute == MiWriteCombined) &&
  1874. ((MI_PDE_MAPS_LARGE_PAGE (PointerPde)) == 0)) {
  1875. PointerPte = MiGetPteAddress (VirtualAddress);
  1876. PteFlushList.Count = 0;
  1877. while (NumberOfPages != 0) {
  1878. TempPte = *PointerPte;
  1879. MI_SET_PTE_WRITE_COMBINE2 (TempPte);
  1880. MI_WRITE_VALID_PTE_NEW_PROTECTION (PointerPte, TempPte);
  1881. if (PteFlushList.Count != MM_MAXIMUM_FLUSH_COUNT) {
  1882. PteFlushList.FlushVa[PteFlushList.Count] = VirtualAddress;
  1883. PteFlushList.Count += 1;
  1884. VirtualAddress = (PVOID) ((PCHAR)VirtualAddress + PAGE_SIZE);
  1885. }
  1886. PointerPte += 1;
  1887. NumberOfPages -= 1;
  1888. }
  1889. MiFlushPteList (&PteFlushList, TRUE);
  1890. }
  1891. }
  1892. PVOID
  1893. MiConvertToLoaderVirtual (
  1894. IN PFN_NUMBER Page,
  1895. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  1896. )
  1897. {
  1898. ULONG_PTR PageAddress;
  1899. PTR_INFO ItrInfo;
  1900. PageAddress = Page << PAGE_SHIFT;
  1901. ItrInfo = &LoaderBlock->u.Ia64.ItrInfo[0];
  1902. if ((ItrInfo[ITR_KERNEL_INDEX].Valid == TRUE) &&
  1903. (PageAddress >= ItrInfo[ITR_KERNEL_INDEX].PhysicalAddress) &&
  1904. (PageAddress <= ItrInfo[ITR_KERNEL_INDEX].PhysicalAddress +
  1905. ((ULONG_PTR)1 << ItrInfo[ITR_KERNEL_INDEX].PageSize))) {
  1906. return (PVOID)(ItrInfo[ITR_KERNEL_INDEX].VirtualAddress +
  1907. (PageAddress - ItrInfo[ITR_KERNEL_INDEX].PhysicalAddress));
  1908. }
  1909. else if ((ItrInfo[ITR_DRIVER0_INDEX].Valid == TRUE) &&
  1910. (PageAddress >= ItrInfo[ITR_DRIVER0_INDEX].PhysicalAddress) &&
  1911. (PageAddress <= ItrInfo[ITR_DRIVER0_INDEX].PhysicalAddress +
  1912. ((ULONG_PTR)1 << ItrInfo[ITR_DRIVER0_INDEX].PageSize))) {
  1913. return (PVOID)(ItrInfo[ITR_DRIVER0_INDEX].VirtualAddress +
  1914. (PageAddress - ItrInfo[ITR_DRIVER0_INDEX].PhysicalAddress));
  1915. }
  1916. else if ((ItrInfo[ITR_DRIVER1_INDEX].Valid == TRUE) &&
  1917. (PageAddress >= ItrInfo[ITR_DRIVER1_INDEX].PhysicalAddress) &&
  1918. (PageAddress <= ItrInfo[ITR_DRIVER1_INDEX].PhysicalAddress +
  1919. ((ULONG_PTR)1 << ItrInfo[ITR_DRIVER1_INDEX].PageSize))) {
  1920. return (PVOID)(ItrInfo[ITR_DRIVER1_INDEX].VirtualAddress +
  1921. (PageAddress - ItrInfo[ITR_DRIVER1_INDEX].PhysicalAddress));
  1922. }
  1923. else {
  1924. KeBugCheckEx (MEMORY_MANAGEMENT,
  1925. 0x01010101,
  1926. PageAddress,
  1927. (ULONG_PTR)&ItrInfo[0],
  1928. (ULONG_PTR)LoaderBlock);
  1929. }
  1930. }
  1931. VOID
  1932. MiBuildPageTableForLoaderMemory (
  1933. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  1934. )
  1935. /*++
  1936. Routine Description:
  1937. This function builds page tables for loader loaded drivers and loader
  1938. allocated memory.
  1939. Arguments:
  1940. LoaderBlock - Supplies the address of the loader block.
  1941. Return Value:
  1942. None.
  1943. --*/
  1944. {
  1945. PMMPTE StartPte;
  1946. PMMPTE EndPte;
  1947. PMMPTE StartPde;
  1948. PMMPTE StartPpe;
  1949. MMPTE TempPte;
  1950. MMPTE TempPte2;
  1951. ULONG First;
  1952. PLIST_ENTRY NextEntry;
  1953. PFN_NUMBER NextPhysicalPage;
  1954. PVOID Va;
  1955. PFN_NUMBER PfnNumber;
  1956. PTR_INFO DtrInfo;
  1957. PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
  1958. TempPte = ValidKernelPte;
  1959. NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
  1960. for ( ; NextEntry != &LoaderBlock->MemoryDescriptorListHead; NextEntry = NextEntry->Flink) {
  1961. MemoryDescriptor = CONTAINING_RECORD(NextEntry,
  1962. MEMORY_ALLOCATION_DESCRIPTOR,
  1963. ListEntry);
  1964. if ((MemoryDescriptor->MemoryType == LoaderOsloaderHeap) ||
  1965. (MemoryDescriptor->MemoryType == LoaderRegistryData) ||
  1966. (MemoryDescriptor->MemoryType == LoaderNlsData) ||
  1967. (MemoryDescriptor->MemoryType == LoaderStartupDpcStack) ||
  1968. (MemoryDescriptor->MemoryType == LoaderStartupKernelStack) ||
  1969. (MemoryDescriptor->MemoryType == LoaderStartupPanicStack) ||
  1970. (MemoryDescriptor->MemoryType == LoaderStartupPdrPage) ||
  1971. (MemoryDescriptor->MemoryType == LoaderMemoryData)) {
  1972. TempPte.u.Hard.Execute = 0;
  1973. }
  1974. else if ((MemoryDescriptor->MemoryType == LoaderSystemCode) ||
  1975. (MemoryDescriptor->MemoryType == LoaderHalCode) ||
  1976. (MemoryDescriptor->MemoryType == LoaderBootDriver) ||
  1977. (MemoryDescriptor->MemoryType == LoaderStartupDpcStack)) {
  1978. TempPte.u.Hard.Execute = 1;
  1979. }
  1980. else {
  1981. continue;
  1982. }
  1983. PfnNumber = MemoryDescriptor->BasePage;
  1984. Va = MiConvertToLoaderVirtual (MemoryDescriptor->BasePage, LoaderBlock);
  1985. StartPte = MiGetPteAddress (Va);
  1986. EndPte = StartPte + MemoryDescriptor->PageCount;
  1987. First = TRUE;
  1988. while (StartPte < EndPte) {
  1989. if (First == TRUE || MiIsPteOnPpeBoundary(StartPte)) {
  1990. StartPpe = MiGetPdeAddress(StartPte);
  1991. if (StartPpe->u.Hard.Valid == 0) {
  1992. ASSERT (StartPpe->u.Long == 0);
  1993. NextPhysicalPage = MiGetNextPhysicalPage ();
  1994. RtlZeroMemory (KSEG_ADDRESS(NextPhysicalPage), PAGE_SIZE);
  1995. TempPte.u.Hard.PageFrameNumber = NextPhysicalPage;
  1996. MI_WRITE_VALID_PTE (StartPpe, TempPte);
  1997. }
  1998. }
  1999. if ((First == TRUE) || MiIsPteOnPdeBoundary(StartPte)) {
  2000. First = FALSE;
  2001. StartPde = MiGetPteAddress (StartPte);
  2002. if (StartPde->u.Hard.Valid == 0) {
  2003. NextPhysicalPage = MiGetNextPhysicalPage ();
  2004. RtlZeroMemory (KSEG_ADDRESS(NextPhysicalPage), PAGE_SIZE);
  2005. TempPte.u.Hard.PageFrameNumber = NextPhysicalPage;
  2006. MI_WRITE_VALID_PTE (StartPde, TempPte);
  2007. }
  2008. }
  2009. TempPte.u.Hard.PageFrameNumber = PfnNumber;
  2010. MI_WRITE_VALID_PTE (StartPte, TempPte);
  2011. StartPte += 1;
  2012. PfnNumber += 1;
  2013. Va = (PVOID)((ULONG_PTR)Va + PAGE_SIZE);
  2014. }
  2015. }
  2016. //
  2017. // Build a mapping for the I/O port space with caching disabled.
  2018. //
  2019. DtrInfo = &LoaderBlock->u.Ia64.DtrInfo[DTR_IO_PORT_INDEX];
  2020. Va = (PVOID) DtrInfo->VirtualAddress;
  2021. PfnNumber = (DtrInfo->PhysicalAddress >> PAGE_SHIFT);
  2022. StartPte = MiGetPteAddress (Va);
  2023. EndPte = MiGetPteAddress (
  2024. (PVOID) ((ULONG_PTR)Va + ((ULONG_PTR)1 << DtrInfo->PageSize) - 1));
  2025. TempPte2 = ValidKernelPte;
  2026. MI_DISABLE_CACHING (TempPte2);
  2027. First = TRUE;
  2028. while (StartPte <= EndPte) {
  2029. if (First == TRUE || MiIsPteOnPpeBoundary (StartPte)) {
  2030. StartPpe = MiGetPdeAddress(StartPte);
  2031. if (StartPpe->u.Hard.Valid == 0) {
  2032. ASSERT (StartPpe->u.Long == 0);
  2033. NextPhysicalPage = MiGetNextPhysicalPage ();
  2034. RtlZeroMemory (KSEG_ADDRESS(NextPhysicalPage), PAGE_SIZE);
  2035. TempPte.u.Hard.PageFrameNumber = NextPhysicalPage;
  2036. MI_WRITE_VALID_PTE (StartPpe, TempPte);
  2037. }
  2038. }
  2039. if ((First == TRUE) || MiIsPteOnPdeBoundary (StartPte)) {
  2040. First = FALSE;
  2041. StartPde = MiGetPteAddress (StartPte);
  2042. if (StartPde->u.Hard.Valid == 0) {
  2043. NextPhysicalPage = MiGetNextPhysicalPage ();
  2044. RtlZeroMemory (KSEG_ADDRESS(NextPhysicalPage), PAGE_SIZE);
  2045. TempPte.u.Hard.PageFrameNumber = NextPhysicalPage;
  2046. MI_WRITE_VALID_PTE (StartPde, TempPte);
  2047. }
  2048. }
  2049. TempPte2.u.Hard.PageFrameNumber = PfnNumber;
  2050. MI_WRITE_VALID_PTE (StartPte, TempPte2);
  2051. StartPte += 1;
  2052. PfnNumber += 1;
  2053. }
  2054. //
  2055. // Build a mapping for the PAL with caching enabled.
  2056. //
  2057. DtrInfo = &LoaderBlock->u.Ia64.DtrInfo[DTR_PAL_INDEX];
  2058. Va = (PVOID) HAL_PAL_VIRTUAL_ADDRESS;
  2059. PfnNumber = (DtrInfo->PhysicalAddress >> PAGE_SHIFT);
  2060. StartPte = MiGetPteAddress (Va);
  2061. EndPte = MiGetPteAddress (
  2062. (PVOID) ((ULONG_PTR)Va + ((ULONG_PTR)1 << DtrInfo->PageSize) - 1));
  2063. TempPte2 = ValidKernelPte;
  2064. First = TRUE;
  2065. while (StartPte <= EndPte) {
  2066. if (First == TRUE || MiIsPteOnPpeBoundary (StartPte)) {
  2067. StartPpe = MiGetPdeAddress(StartPte);
  2068. if (StartPpe->u.Hard.Valid == 0) {
  2069. ASSERT (StartPpe->u.Long == 0);
  2070. NextPhysicalPage = MiGetNextPhysicalPage ();
  2071. RtlZeroMemory (KSEG_ADDRESS(NextPhysicalPage), PAGE_SIZE);
  2072. TempPte.u.Hard.PageFrameNumber = NextPhysicalPage;
  2073. MI_WRITE_VALID_PTE (StartPpe, TempPte);
  2074. }
  2075. }
  2076. if ((First == TRUE) || MiIsPteOnPdeBoundary (StartPte)) {
  2077. First = FALSE;
  2078. StartPde = MiGetPteAddress (StartPte);
  2079. if (StartPde->u.Hard.Valid == 0) {
  2080. NextPhysicalPage = MiGetNextPhysicalPage ();
  2081. RtlZeroMemory (KSEG_ADDRESS(NextPhysicalPage), PAGE_SIZE);
  2082. TempPte.u.Hard.PageFrameNumber = NextPhysicalPage;
  2083. MI_WRITE_VALID_PTE (StartPde, TempPte);
  2084. }
  2085. }
  2086. TempPte2.u.Hard.PageFrameNumber = PfnNumber;
  2087. MI_WRITE_VALID_PTE (StartPte, TempPte2);
  2088. StartPte += 1;
  2089. PfnNumber += 1;
  2090. }
  2091. }
  2092. VOID
  2093. MiRemoveLoaderSuperPages (
  2094. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  2095. )
  2096. {
  2097. //
  2098. // Remove the super page fixed TB entries used for the boot drivers.
  2099. //
  2100. if (LoaderBlock->u.Ia64.ItrInfo[ITR_DRIVER0_INDEX].Valid) {
  2101. KiFlushFixedInstTb(FALSE, LoaderBlock->u.Ia64.ItrInfo[ITR_DRIVER0_INDEX].VirtualAddress);
  2102. }
  2103. if (LoaderBlock->u.Ia64.ItrInfo[ITR_DRIVER1_INDEX].Valid) {
  2104. KiFlushFixedInstTb(FALSE, LoaderBlock->u.Ia64.ItrInfo[ITR_DRIVER1_INDEX].VirtualAddress);
  2105. }
  2106. if (LoaderBlock->u.Ia64.DtrInfo[DTR_DRIVER0_INDEX].Valid) {
  2107. KiFlushFixedDataTb(FALSE, LoaderBlock->u.Ia64.DtrInfo[DTR_DRIVER0_INDEX].VirtualAddress);
  2108. }
  2109. if (LoaderBlock->u.Ia64.DtrInfo[DTR_DRIVER1_INDEX].Valid) {
  2110. KiFlushFixedDataTb(FALSE, LoaderBlock->u.Ia64.DtrInfo[DTR_DRIVER1_INDEX].VirtualAddress);
  2111. }
  2112. if (LoaderBlock->u.Ia64.DtrInfo[DTR_IO_PORT_INDEX].Valid) {
  2113. KiFlushFixedDataTb(FALSE, LoaderBlock->u.Ia64.DtrInfo[DTR_IO_PORT_INDEX].VirtualAddress);
  2114. }
  2115. }
  2116. VOID
  2117. MiCompactMemoryDescriptorList (
  2118. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  2119. )
  2120. {
  2121. PFN_NUMBER KernelStart;
  2122. PFN_NUMBER KernelEnd;
  2123. ULONG_PTR PageSize;
  2124. PLIST_ENTRY NextEntry;
  2125. PLIST_ENTRY PreviousEntry;
  2126. PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
  2127. PMEMORY_ALLOCATION_DESCRIPTOR PreviousMemoryDescriptor;
  2128. KernelStart = MiNtoskrnlPhysicalBase >> PAGE_SHIFT;
  2129. PageSize = (ULONG_PTR)1 << MiNtoskrnlPageShift;
  2130. KernelEnd = KernelStart + (PageSize >> PAGE_SHIFT);
  2131. PreviousMemoryDescriptor = NULL;
  2132. PreviousEntry = NULL;
  2133. NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
  2134. for ( ; NextEntry != &LoaderBlock->MemoryDescriptorListHead; NextEntry = NextEntry->Flink) {
  2135. MemoryDescriptor = CONTAINING_RECORD(NextEntry,
  2136. MEMORY_ALLOCATION_DESCRIPTOR,
  2137. ListEntry);
  2138. if ((MemoryDescriptor->BasePage >= KernelStart) &&
  2139. (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount <= KernelEnd)) {
  2140. if (MemoryDescriptor->MemoryType == LoaderSystemBlock) {
  2141. MemoryDescriptor->MemoryType = LoaderFirmwareTemporary;
  2142. }
  2143. else if (MemoryDescriptor->MemoryType == LoaderSpecialMemory) {
  2144. MemoryDescriptor->MemoryType = LoaderFirmwareTemporary;
  2145. }
  2146. }
  2147. if ((PreviousMemoryDescriptor != NULL) &&
  2148. (MemoryDescriptor->MemoryType == PreviousMemoryDescriptor->MemoryType) &&
  2149. (MemoryDescriptor->BasePage ==
  2150. (PreviousMemoryDescriptor->BasePage + PreviousMemoryDescriptor->PageCount))) {
  2151. PreviousMemoryDescriptor->PageCount += MemoryDescriptor->PageCount;
  2152. RemoveEntryList (NextEntry);
  2153. }
  2154. else {
  2155. PreviousMemoryDescriptor = MemoryDescriptor;
  2156. PreviousEntry = NextEntry;
  2157. }
  2158. }
  2159. }
  2160. VOID
  2161. MiInitializeTbImage (
  2162. VOID
  2163. )
  2164. /*++
  2165. Routine Description:
  2166. Initialize the software map of the translation register mappings wired
  2167. into the TB by the loader.
  2168. Arguments:
  2169. None.
  2170. Return Value:
  2171. None.
  2172. Environment:
  2173. Kernel mode, Phase 0 INIT only so no locks needed.
  2174. --*/
  2175. {
  2176. ULONG PageSize;
  2177. PFN_NUMBER BasePage;
  2178. ULONG_PTR TranslationLength;
  2179. ULONG_PTR BaseAddress;
  2180. ULONG_PTR EndAddress;
  2181. PTR_INFO TranslationRegisterEntry;
  2182. PTR_INFO AliasTranslationRegisterEntry;
  2183. PTR_INFO LastTranslationRegisterEntry;
  2184. //
  2185. // Snap the boot TRs.
  2186. //
  2187. RtlCopyMemory (&MiBootedTrInfo[0],
  2188. &KeLoaderBlock->u.Ia64.ItrInfo[0],
  2189. NUMBER_OF_LOADER_TR_ENTRIES * sizeof (TR_INFO));
  2190. RtlCopyMemory (&MiBootedTrInfo[NUMBER_OF_LOADER_TR_ENTRIES],
  2191. &KeLoaderBlock->u.Ia64.DtrInfo[0],
  2192. NUMBER_OF_LOADER_TR_ENTRIES * sizeof (TR_INFO));
  2193. //
  2194. // Capture information regarding the translation register entry that
  2195. // maps the kernel.
  2196. //
  2197. LastTranslationRegisterEntry = MiTrInfo;
  2198. TranslationRegisterEntry = &KeLoaderBlock->u.Ia64.ItrInfo[ITR_KERNEL_INDEX];
  2199. AliasTranslationRegisterEntry = TranslationRegisterEntry + NUMBER_OF_LOADER_TR_ENTRIES;
  2200. ASSERT (TranslationRegisterEntry->PageSize != 0);
  2201. ASSERT (TranslationRegisterEntry->PageSize == AliasTranslationRegisterEntry->PageSize);
  2202. ASSERT (TranslationRegisterEntry->VirtualAddress == AliasTranslationRegisterEntry->VirtualAddress);
  2203. ASSERT (TranslationRegisterEntry->PhysicalAddress == AliasTranslationRegisterEntry->PhysicalAddress);
  2204. *LastTranslationRegisterEntry = *TranslationRegisterEntry;
  2205. //
  2206. // Calculate the ending address for each range to speed up
  2207. // subsequent searches.
  2208. //
  2209. PageSize = TranslationRegisterEntry->PageSize;
  2210. ASSERT (PageSize != 0);
  2211. BaseAddress = TranslationRegisterEntry->VirtualAddress;
  2212. TranslationLength = 1 << PageSize;
  2213. BasePage = MI_VA_TO_PAGE (TranslationRegisterEntry->PhysicalAddress);
  2214. MiAddCachedRange (BasePage,
  2215. BasePage + BYTES_TO_PAGES (TranslationLength) - 1);
  2216. //
  2217. // Initialize the kseg0 variables purely for the debugger.
  2218. //
  2219. MiKseg0Start = (PVOID) TranslationRegisterEntry->VirtualAddress;
  2220. MiKseg0End = (PVOID) ((PCHAR) MiKseg0Start + TranslationLength);
  2221. MiKseg0Mapping = TRUE;
  2222. MiKseg0StartFrame = BasePage;
  2223. MiKseg0EndFrame = BasePage + BYTES_TO_PAGES (TranslationLength) - 1;
  2224. EndAddress = BaseAddress + TranslationLength;
  2225. LastTranslationRegisterEntry->PhysicalAddress = EndAddress;
  2226. MiLastTrEntry = LastTranslationRegisterEntry + 1;
  2227. //
  2228. // Add in the KSEG3 range.
  2229. //
  2230. MiAddTrEntry (KSEG3_BASE, KSEG3_LIMIT);
  2231. //
  2232. // Add in the PCR range.
  2233. //
  2234. MiAddTrEntry ((ULONG_PTR)PCR, (ULONG_PTR)PCR + PAGE_SIZE);
  2235. return;
  2236. }
  2237. VOID
  2238. MiAddTrEntry (
  2239. ULONG_PTR BaseAddress,
  2240. ULONG_PTR EndAddress
  2241. )
  2242. /*++
  2243. Routine Description:
  2244. Add a translation cache entry to our software table.
  2245. Arguments:
  2246. BaseAddress - Supplies the starting virtual address of the range.
  2247. EndAddress - Supplies the ending virtual address of the range.
  2248. Return Value:
  2249. None.
  2250. Environment:
  2251. Kernel mode, Phase 0 INIT only so no locks needed.
  2252. --*/
  2253. {
  2254. PTR_INFO TranslationRegisterEntry;
  2255. if ((MiLastTrEntry == NULL) ||
  2256. (MiLastTrEntry == MiTrInfo + NUMBER_OF_LOADER_TR_ENTRIES)) {
  2257. //
  2258. // This should never happen.
  2259. //
  2260. KeBugCheckEx (MEMORY_MANAGEMENT,
  2261. 0x02020202,
  2262. (ULONG_PTR) MiTrInfo,
  2263. (ULONG_PTR) MiLastTrEntry,
  2264. NUMBER_OF_LOADER_TR_ENTRIES);
  2265. }
  2266. TranslationRegisterEntry = MiLastTrEntry;
  2267. TranslationRegisterEntry->VirtualAddress = (ULONGLONG) BaseAddress;
  2268. TranslationRegisterEntry->PhysicalAddress = (ULONGLONG) EndAddress;
  2269. TranslationRegisterEntry->PageSize = 1;
  2270. MiLastTrEntry += 1;
  2271. return;
  2272. }
  2273. LOGICAL
  2274. MiIsVirtualAddressMappedByTr (
  2275. IN PVOID VirtualAddress
  2276. )
  2277. /*++
  2278. Routine Description:
  2279. For a given virtual address this function returns TRUE if no page fault
  2280. will occur for a read operation on the address, FALSE otherwise.
  2281. Note that after this routine was called, if appropriate locks are not
  2282. held, a non-faulting address could fault.
  2283. Arguments:
  2284. VirtualAddress - Supplies the virtual address to check.
  2285. Return Value:
  2286. TRUE if no page fault would be generated reading the virtual address,
  2287. FALSE otherwise.
  2288. Environment:
  2289. Kernel mode.
  2290. --*/
  2291. {
  2292. ULONG i;
  2293. ULONG PageSize;
  2294. PMMPFN Pfn1;
  2295. PFN_NUMBER BasePage;
  2296. PFN_NUMBER PageCount;
  2297. PTR_INFO TranslationRegisterEntry;
  2298. ULONG_PTR TranslationLength;
  2299. ULONG_PTR BaseAddress;
  2300. ULONG_PTR EndAddress;
  2301. PFN_NUMBER PageFrameIndex;
  2302. PLIST_ENTRY NextMd;
  2303. PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
  2304. if ((VirtualAddress >= (PVOID)KSEG3_BASE) && (VirtualAddress < (PVOID)KSEG3_LIMIT)) {
  2305. //
  2306. // Bound this with the actual physical pages so that a busted
  2307. // debugger access can't tube the machine. Note only pages
  2308. // with attributes of fully cached should be accessed this way
  2309. // to avoid corrupting the TB.
  2310. //
  2311. // N.B. You cannot use the line below as on IA64 this translates
  2312. // into a direct TB query (tpa) and this address has not been
  2313. // validated against the actual PFNs. Instead, convert it manually
  2314. // and then validate it.
  2315. //
  2316. // PageFrameIndex = MI_CONVERT_PHYSICAL_TO_PFN (VirtualAddress);
  2317. //
  2318. PageFrameIndex = (ULONG_PTR)VirtualAddress - KSEG3_BASE;
  2319. PageFrameIndex = MI_VA_TO_PAGE (PageFrameIndex);
  2320. if (MmPhysicalMemoryBlock != NULL) {
  2321. if (MI_IS_PFN (PageFrameIndex)) {
  2322. Pfn1 = MI_PFN_ELEMENT (PageFrameIndex);
  2323. if ((Pfn1->u3.e1.CacheAttribute == MiCached) ||
  2324. (Pfn1->u3.e1.CacheAttribute == MiNotMapped)) {
  2325. return TRUE;
  2326. }
  2327. }
  2328. return FALSE;
  2329. }
  2330. //
  2331. // Walk loader blocks as it's all we have.
  2332. //
  2333. NextMd = KeLoaderBlock->MemoryDescriptorListHead.Flink;
  2334. while (NextMd != &KeLoaderBlock->MemoryDescriptorListHead) {
  2335. MemoryDescriptor = CONTAINING_RECORD (NextMd,
  2336. MEMORY_ALLOCATION_DESCRIPTOR,
  2337. ListEntry);
  2338. BasePage = MemoryDescriptor->BasePage;
  2339. PageCount = MemoryDescriptor->PageCount;
  2340. if ((PageFrameIndex >= BasePage) &&
  2341. (PageFrameIndex < BasePage + PageCount)) {
  2342. //
  2343. // Changes to the memory type requirements below need
  2344. // to be done carefully as the debugger may not only
  2345. // accidentally try to read this range, it may try
  2346. // to write it !
  2347. //
  2348. switch (MemoryDescriptor->MemoryType) {
  2349. case LoaderFree:
  2350. case LoaderLoadedProgram:
  2351. case LoaderFirmwareTemporary:
  2352. case LoaderOsloaderStack:
  2353. return TRUE;
  2354. }
  2355. return FALSE;
  2356. }
  2357. NextMd = MemoryDescriptor->ListEntry.Flink;
  2358. }
  2359. return FALSE;
  2360. }
  2361. if (MiMappingsInitialized == FALSE) {
  2362. TranslationRegisterEntry = &KeLoaderBlock->u.Ia64.ItrInfo[0];
  2363. }
  2364. else {
  2365. TranslationRegisterEntry = &MiTrInfo[0];
  2366. }
  2367. //
  2368. // Examine the 8 icache & dcache TR entries looking for a match.
  2369. // It is too bad this the number of entries is hardcoded into the
  2370. // loader block. Since it is this way, assume also that the ITR
  2371. // and DTR entries are contiguous and just keep walking into the DTR
  2372. // if a match cannot be found in the ITR.
  2373. //
  2374. for (i = 0; i < 2 * NUMBER_OF_LOADER_TR_ENTRIES; i += 1) {
  2375. PageSize = TranslationRegisterEntry->PageSize;
  2376. if (PageSize != 0) {
  2377. BaseAddress = TranslationRegisterEntry->VirtualAddress;
  2378. //
  2379. // Convert PageSize (really the power of 2 to use) into the
  2380. // correct byte length the translation maps. Note that the MiTrInfo
  2381. // is already converted.
  2382. //
  2383. if (MiMappingsInitialized == FALSE) {
  2384. TranslationLength = 1;
  2385. while (PageSize != 0) {
  2386. TranslationLength = TranslationLength << 1;
  2387. PageSize -= 1;
  2388. }
  2389. EndAddress = BaseAddress + TranslationLength;
  2390. }
  2391. else {
  2392. EndAddress = TranslationRegisterEntry->PhysicalAddress;
  2393. }
  2394. if ((VirtualAddress >= (PVOID) BaseAddress) &&
  2395. (VirtualAddress < (PVOID) EndAddress)) {
  2396. return TRUE;
  2397. }
  2398. }
  2399. TranslationRegisterEntry += 1;
  2400. if (TranslationRegisterEntry == MiLastTrEntry) {
  2401. break;
  2402. }
  2403. }
  2404. return FALSE;
  2405. }