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.

314 lines
7.3 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. xxmemory.c
  5. Abstract:
  6. Provides routines to allow the HAL to map physical memory.
  7. Author:
  8. John Vert (jvert) 3-Sep-1991
  9. Environment:
  10. Phase 0 initialization only.
  11. Revision History:
  12. --*/
  13. #include "halp.h"
  14. #ifdef ALLOC_PRAGMA
  15. #pragma alloc_text(INIT,HalpAllocPhysicalMemory)
  16. #endif
  17. MEMORY_ALLOCATION_DESCRIPTOR HalpExtraAllocationDescriptor;
  18. PVOID
  19. HalpMapPhysicalMemory(
  20. IN PHYSICAL_ADDRESS PhysicalAddress,
  21. IN ULONG NumberPages,
  22. IN MEMORY_CACHING_TYPE CacheType
  23. )
  24. /*++
  25. Routine Description:
  26. This routine maps physical memory into the area of virtual memory
  27. reserved for the HAL.
  28. Arguments:
  29. PhysicalAddress - Supplies the physical address of the start of the
  30. area of physical memory to be mapped.
  31. NumberPages - This is not used for IA64. It is here just to keep the
  32. interface consistent.
  33. Return Value:
  34. PVOID - Virtual address at which the requested block of physical memory
  35. was mapped
  36. NULL - The requested block of physical memory could not be mapped.
  37. --*/
  38. {
  39. if (CacheType == MmCached) {
  40. return (PVOID)(((ULONG_PTR)KSEG_ADDRESS(PhysicalAddress.QuadPart >> PAGE_SHIFT)) |
  41. (PhysicalAddress.QuadPart & ~(-1 << PAGE_SHIFT)));
  42. } else {
  43. return (PVOID)(((ULONG_PTR)KSEG4_ADDRESS(PhysicalAddress.QuadPart >> PAGE_SHIFT)) |
  44. (PhysicalAddress.QuadPart & ~(-1 << PAGE_SHIFT)));
  45. }
  46. }
  47. PVOID
  48. HalpMapPhysicalMemory64(
  49. IN PHYSICAL_ADDRESS PhysicalAddress,
  50. IN ULONG NumberPages
  51. )
  52. /*++
  53. Routine Description:
  54. Maps a physical memory address into virtual space by calling HalpMapPhysicalMemory but
  55. always in the MmNonCached mode. MMIO.
  56. Arguments:
  57. PhysicalAddress - Supplies a physical address of the memory to be mapped
  58. NumberPages - Number of pages to map
  59. Return Value:
  60. Virtual address pointer to the requested physical address
  61. --*/
  62. {
  63. return HalpMapPhysicalMemory(PhysicalAddress, NumberPages, MmNonCached);
  64. } // HalpMapPhysicalMemory64()
  65. VOID
  66. HalpUnmapVirtualAddress(
  67. IN PVOID VirtualAddress,
  68. IN ULONG NumberPages
  69. )
  70. /*++
  71. Routine Description:
  72. Release PTEs previously allocated to map memory by
  73. HalpMapPhysicalMemory.
  74. Note: This routine does not free memory, it only releases
  75. the Virtual to Physical translation.
  76. Arguments:
  77. VirtualAddress Supplied the base VA of the address range to be
  78. released.
  79. NumberPages Supplied the length of the range.
  80. Return Value.
  81. None.
  82. --*/
  83. {
  84. //
  85. // HalpMapPhysicalMemory returns an address in KSEG4 and it doesn't use a
  86. // page table, so no need to unmap.
  87. //
  88. // MmUnmapIoSpace(VirtualAddress, PAGE_SIZE * NumberPages);
  89. return;
  90. }
  91. PVOID
  92. HalpAllocPhysicalMemory(
  93. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  94. IN ULONG_PTR MaxPhysicalAddress,
  95. IN ULONG NoPages,
  96. IN BOOLEAN bAlignOn64k
  97. )
  98. /*++
  99. Routine Description:
  100. Carves out N pages of physical memory from the memory descriptor
  101. list in the desired location. This function is to be called only
  102. during phase zero initialization. (ie, before the kernel's memory
  103. management system is running)
  104. Arguments:
  105. MaxPhysicalAddress - The max address where the physical memory can be
  106. NoPages - Number of pages to allocate
  107. Return Value:
  108. The physical address or NULL if the memory could not be obtained.
  109. --*/
  110. {
  111. PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
  112. PLIST_ENTRY NextMd;
  113. ULONG AlignmentOffset;
  114. ULONG_PTR MaxPageAddress;
  115. ULONG_PTR PhysicalAddress;
  116. MaxPageAddress = MaxPhysicalAddress >> PAGE_SHIFT;
  117. //
  118. // Scan the memory allocation descriptors and allocate map buffers
  119. //
  120. NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
  121. while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
  122. Descriptor = CONTAINING_RECORD(
  123. NextMd,
  124. MEMORY_ALLOCATION_DESCRIPTOR,
  125. ListEntry
  126. );
  127. AlignmentOffset = bAlignOn64k ?
  128. ((Descriptor->BasePage + 0x0f) & ~0x0f) - Descriptor->BasePage :
  129. 0;
  130. //
  131. // Search for a block of memory which is contains a memory chuck
  132. // that is greater than size pages, and has a physical address less
  133. // than MAXIMUM_PHYSICAL_ADDRESS.
  134. //
  135. if ((Descriptor->MemoryType == LoaderFree ||
  136. Descriptor->MemoryType == MemoryFirmwareTemporary) &&
  137. (Descriptor->BasePage) &&
  138. (Descriptor->PageCount >= NoPages + AlignmentOffset) &&
  139. (Descriptor->BasePage + NoPages + AlignmentOffset < MaxPageAddress)) {
  140. PhysicalAddress =
  141. (Descriptor->BasePage + AlignmentOffset) << PAGE_SHIFT;
  142. break;
  143. }
  144. NextMd = NextMd->Flink;
  145. }
  146. //
  147. // Use the extra descriptor to define the memory at the end of the
  148. // original block.
  149. //
  150. ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
  151. if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
  152. return 0;
  153. //
  154. // Adjust the memory descriptors.
  155. //
  156. if (AlignmentOffset == 0) {
  157. Descriptor->BasePage += NoPages;
  158. Descriptor->PageCount -= NoPages;
  159. if (Descriptor->PageCount == 0) {
  160. //
  161. // The whole block was allocated,
  162. // Remove the entry from the list completely.
  163. //
  164. RemoveEntryList(&Descriptor->ListEntry);
  165. }
  166. } else {
  167. if (Descriptor->PageCount - NoPages - AlignmentOffset) {
  168. //
  169. // Currently we only allow one Align64K allocation
  170. //
  171. ASSERT (HalpExtraAllocationDescriptor.PageCount == 0);
  172. //
  173. // The extra descriptor is needed so intialize it and insert
  174. // it in the list.
  175. //
  176. HalpExtraAllocationDescriptor.PageCount =
  177. Descriptor->PageCount - NoPages - AlignmentOffset;
  178. HalpExtraAllocationDescriptor.BasePage =
  179. Descriptor->BasePage + NoPages + AlignmentOffset;
  180. HalpExtraAllocationDescriptor.MemoryType = MemoryFree;
  181. InsertHeadList(
  182. &Descriptor->ListEntry,
  183. &HalpExtraAllocationDescriptor.ListEntry
  184. );
  185. }
  186. //
  187. // Use the current entry as the descriptor for the first block.
  188. //
  189. Descriptor->PageCount = AlignmentOffset;
  190. }
  191. return (PVOID)PhysicalAddress;
  192. }
  193. BOOLEAN
  194. HalpVirtualToPhysical(
  195. IN ULONG_PTR VirtualAddress,
  196. OUT PPHYSICAL_ADDRESS PhysicalAddress
  197. )
  198. {
  199. if (VirtualAddress >= KSEG3_BASE && VirtualAddress < KSEG3_LIMIT) {
  200. PhysicalAddress->QuadPart = VirtualAddress - KSEG3_BASE;
  201. } else if (VirtualAddress >= KSEG4_BASE && VirtualAddress < KSEG4_LIMIT) {
  202. PhysicalAddress->QuadPart = VirtualAddress - KSEG4_BASE;
  203. } else {
  204. return FALSE;
  205. }
  206. return TRUE;
  207. }