Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmemory.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS HAL 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: hal/halx86/generic/memory.c 00005 * PURPOSE: HAL memory management 00006 * PROGRAMMERS: ReactOS Portable Systems Group 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #include <hal.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* Share with Mm headers? */ 00016 #define MM_HAL_HEAP_START (PVOID)(MM_HAL_VA_START + (1024 * 1024)) 00017 00018 /* GLOBALS *******************************************************************/ 00019 00020 ULONG HalpUsedAllocDescriptors; 00021 MEMORY_ALLOCATION_DESCRIPTOR HalpAllocationDescriptorArray[64]; 00022 PVOID HalpHeapStart = MM_HAL_HEAP_START; 00023 00024 00025 /* PRIVATE FUNCTIONS *********************************************************/ 00026 00027 ULONG_PTR 00028 NTAPI 00029 HalpAllocPhysicalMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 00030 IN ULONG_PTR MaxAddress, 00031 IN PFN_NUMBER PageCount, 00032 IN BOOLEAN Aligned) 00033 { 00034 ULONG UsedDescriptors; 00035 ULONG_PTR PhysicalAddress; 00036 PFN_NUMBER MaxPage, BasePage, Alignment; 00037 PLIST_ENTRY NextEntry; 00038 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock, NewBlock, FreeBlock; 00039 00040 /* Highest page we'll go */ 00041 MaxPage = MaxAddress >> PAGE_SHIFT; 00042 00043 /* We need at least two blocks */ 00044 if ((HalpUsedAllocDescriptors + 2) > 64) return 0; 00045 00046 /* Remember how many we have now */ 00047 UsedDescriptors = HalpUsedAllocDescriptors; 00048 00049 /* Loop the loader block memory descriptors */ 00050 NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink; 00051 while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) 00052 { 00053 /* Get the block */ 00054 MdBlock = CONTAINING_RECORD(NextEntry, 00055 MEMORY_ALLOCATION_DESCRIPTOR, 00056 ListEntry); 00057 00058 /* No alignment by default */ 00059 Alignment = 0; 00060 00061 /* Unless requested, in which case we use a 64KB block alignment */ 00062 if (Aligned) Alignment = ((MdBlock->BasePage + 0x0F) & ~0x0F) - MdBlock->BasePage; 00063 00064 /* Search for free memory */ 00065 if ((MdBlock->MemoryType == LoaderFree) || 00066 (MdBlock->MemoryType == LoaderFirmwareTemporary)) 00067 { 00068 /* Make sure the page is within bounds, including alignment */ 00069 BasePage = MdBlock->BasePage; 00070 if ((BasePage) && 00071 (MdBlock->PageCount >= PageCount + Alignment) && 00072 (BasePage + PageCount + Alignment < MaxPage)) 00073 { 00074 00075 /* We found an address */ 00076 PhysicalAddress = (BasePage + Alignment) << PAGE_SHIFT; 00077 break; 00078 } 00079 } 00080 00081 /* Keep trying */ 00082 NextEntry = NextEntry->Flink; 00083 } 00084 00085 /* If we didn't find anything, get out of here */ 00086 if (NextEntry == &LoaderBlock->MemoryDescriptorListHead) return 0; 00087 00088 /* Okay, now get a descriptor */ 00089 NewBlock = &HalpAllocationDescriptorArray[HalpUsedAllocDescriptors]; 00090 NewBlock->PageCount = (ULONG)PageCount; 00091 NewBlock->BasePage = MdBlock->BasePage + Alignment; 00092 NewBlock->MemoryType = LoaderHALCachedMemory; 00093 00094 /* Update count */ 00095 UsedDescriptors++; 00096 HalpUsedAllocDescriptors = UsedDescriptors; 00097 00098 /* Check if we had any alignment */ 00099 if (Alignment) 00100 { 00101 /* Check if we had leftovers */ 00102 if (MdBlock->PageCount > (PageCount + Alignment)) 00103 { 00104 /* Get the next descriptor */ 00105 FreeBlock = &HalpAllocationDescriptorArray[UsedDescriptors]; 00106 FreeBlock->PageCount = MdBlock->PageCount - Alignment - (ULONG)PageCount; 00107 FreeBlock->BasePage = MdBlock->BasePage + Alignment + (ULONG)PageCount; 00108 00109 /* One more */ 00110 HalpUsedAllocDescriptors++; 00111 00112 /* Insert it into the list */ 00113 InsertHeadList(&MdBlock->ListEntry, &FreeBlock->ListEntry); 00114 } 00115 00116 /* Trim the original block to the alignment only */ 00117 MdBlock->PageCount = Alignment; 00118 00119 /* Insert the descriptor after the original one */ 00120 InsertHeadList(&MdBlock->ListEntry, &NewBlock->ListEntry); 00121 } 00122 else 00123 { 00124 /* Consume memory from this block */ 00125 MdBlock->BasePage += (ULONG)PageCount; 00126 MdBlock->PageCount -= (ULONG)PageCount; 00127 00128 /* Insert the descriptor before the original one */ 00129 InsertTailList(&MdBlock->ListEntry, &NewBlock->ListEntry); 00130 00131 /* Remove the entry if the whole block was allocated */ 00132 if (MdBlock->PageCount == 0) RemoveEntryList(&MdBlock->ListEntry); 00133 } 00134 00135 /* Return the address */ 00136 return PhysicalAddress; 00137 } 00138 00139 PVOID 00140 NTAPI 00141 HalpMapPhysicalMemory64(IN PHYSICAL_ADDRESS PhysicalAddress, 00142 IN PFN_COUNT PageCount) 00143 { 00144 PHARDWARE_PTE PointerPte; 00145 PFN_NUMBER UsedPages = 0; 00146 PVOID VirtualAddress, BaseAddress; 00147 00148 /* Start at the current HAL heap base */ 00149 BaseAddress = HalpHeapStart; 00150 VirtualAddress = BaseAddress; 00151 00152 /* Loop until we have all the pages required */ 00153 while (UsedPages < PageCount) 00154 { 00155 /* If this overflows past the HAL heap, it means there's no space */ 00156 if (VirtualAddress == NULL) return NULL; 00157 00158 /* Get the PTE for this address */ 00159 PointerPte = HalAddressToPte(VirtualAddress); 00160 00161 /* Go to the next page */ 00162 VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress + PAGE_SIZE); 00163 00164 /* Check if the page is available */ 00165 if (PointerPte->Valid) 00166 { 00167 /* PTE has data, skip it and start with a new base address */ 00168 BaseAddress = VirtualAddress; 00169 UsedPages = 0; 00170 continue; 00171 } 00172 00173 /* PTE is available, keep going on this run */ 00174 UsedPages++; 00175 } 00176 00177 /* Take the base address of the page plus the actual offset in the address */ 00178 VirtualAddress = (PVOID)((ULONG_PTR)BaseAddress + 00179 BYTE_OFFSET(PhysicalAddress.LowPart)); 00180 00181 /* If we are starting at the heap, move the heap */ 00182 if (BaseAddress == HalpHeapStart) 00183 { 00184 /* Past this allocation */ 00185 HalpHeapStart = (PVOID)((ULONG_PTR)BaseAddress + (PageCount * PAGE_SIZE)); 00186 } 00187 00188 /* Loop pages that can be mapped */ 00189 while (UsedPages--) 00190 { 00191 /* Fill out the PTE */ 00192 PointerPte = HalAddressToPte(BaseAddress); 00193 PointerPte->PageFrameNumber = (PFN_NUMBER)(PhysicalAddress.QuadPart >> PAGE_SHIFT); 00194 PointerPte->Valid = 1; 00195 PointerPte->Write = 1; 00196 00197 /* Move to the next address */ 00198 PhysicalAddress.QuadPart += PAGE_SIZE; 00199 BaseAddress = (PVOID)((ULONG_PTR)BaseAddress + PAGE_SIZE); 00200 } 00201 00202 /* Flush the TLB and return the address */ 00203 HalpFlushTLB(); 00204 return VirtualAddress; 00205 } 00206 00207 VOID 00208 NTAPI 00209 HalpUnmapVirtualAddress(IN PVOID VirtualAddress, 00210 IN PFN_COUNT PageCount) 00211 { 00212 PHARDWARE_PTE PointerPte; 00213 ULONG i; 00214 00215 /* Only accept valid addresses */ 00216 if (VirtualAddress < (PVOID)MM_HAL_VA_START) return; 00217 00218 /* Align it down to page size */ 00219 VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress & ~(PAGE_SIZE - 1)); 00220 00221 /* Loop PTEs */ 00222 PointerPte = HalAddressToPte(VirtualAddress); 00223 for (i = 0; i < PageCount; i++) 00224 { 00225 *(PULONG)PointerPte = 0; 00226 PointerPte++; 00227 } 00228 00229 /* Flush the TLB */ 00230 HalpFlushTLB(); 00231 00232 /* Put the heap back */ 00233 if (HalpHeapStart > VirtualAddress) HalpHeapStart = VirtualAddress; 00234 } 00235 Generated on Sun May 27 2012 04:18:13 for ReactOS by
1.7.6.1
|