3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: hal/halx86/generic/memory.c
5 * PURPOSE: HAL memory management
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES ******************************************************************/
15 /* Share with Mm headers? */
16 #define MM_HAL_VA_START (PVOID)0xFFC00000
17 #define MM_HAL_HEAP_START (PVOID)((ULONG_PTR)MM_HAL_VA_START + (1024 * 1024))
19 /* GLOBALS *******************************************************************/
21 ULONG HalpUsedAllocDescriptors
;
22 MEMORY_ALLOCATION_DESCRIPTOR HalpAllocationDescriptorArray
[64];
23 PVOID HalpHeapStart
= MM_HAL_HEAP_START
;
26 /* PRIVATE FUNCTIONS *********************************************************/
31 HalpAllocPhysicalMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
36 ULONG UsedDescriptors
, Alignment
, PhysicalAddress
;
37 PFN_NUMBER MaxPage
, BasePage
;
38 PLIST_ENTRY NextEntry
;
39 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
, NewBlock
, FreeBlock
;
41 /* Highest page we'll go */
42 MaxPage
= MaxAddress
>> PAGE_SHIFT
;
44 /* We need at least two blocks */
45 if ((HalpUsedAllocDescriptors
+ 2) > 64) return 0;
47 /* Remember how many we have now */
48 UsedDescriptors
= HalpUsedAllocDescriptors
;
50 /* Loop the loader block memory descriptors */
51 NextEntry
= LoaderBlock
->MemoryDescriptorListHead
.Flink
;
52 while (NextEntry
!= &LoaderBlock
->MemoryDescriptorListHead
)
55 MdBlock
= CONTAINING_RECORD(NextEntry
,
56 MEMORY_ALLOCATION_DESCRIPTOR
,
59 /* No alignment by default */
62 /* Unless requested, in which case we use a 64KB block alignment */
63 if (Aligned
) Alignment
= ((MdBlock
->BasePage
+ 0x0F) & ~0x0F) - MdBlock
->BasePage
;
65 /* Search for free memory */
66 if ((MdBlock
->MemoryType
== LoaderFree
) ||
67 (MdBlock
->MemoryType
== LoaderFirmwareTemporary
))
69 /* Make sure the page is within bounds, including alignment */
70 BasePage
= MdBlock
->BasePage
;
72 (MdBlock
->PageCount
>= PageCount
+ Alignment
) &&
73 (BasePage
+ PageCount
+ Alignment
< MaxPage
))
76 /* We found an address */
77 PhysicalAddress
= (BasePage
+ Alignment
) << PAGE_SHIFT
;
83 NextEntry
= NextEntry
->Flink
;
86 /* If we didn't find anything, get out of here */
87 if (NextEntry
== &LoaderBlock
->MemoryDescriptorListHead
) return 0;
89 /* Okay, now get a descriptor */
90 NewBlock
= &HalpAllocationDescriptorArray
[HalpUsedAllocDescriptors
];
91 NewBlock
->PageCount
= PageCount
;
92 NewBlock
->BasePage
= MdBlock
->BasePage
+ Alignment
;
93 NewBlock
->MemoryType
= LoaderHALCachedMemory
;
97 HalpUsedAllocDescriptors
= UsedDescriptors
;
99 /* Check if we had any alignment */
102 /* Check if we had leftovers */
103 if ((MdBlock
->PageCount
- Alignment
) != PageCount
)
105 /* Get the next descriptor */
106 FreeBlock
= &HalpAllocationDescriptorArray
[UsedDescriptors
];
107 FreeBlock
->PageCount
= MdBlock
->PageCount
- Alignment
- PageCount
;
108 FreeBlock
->BasePage
= MdBlock
->BasePage
+ Alignment
+ PageCount
;
111 HalpUsedAllocDescriptors
++;
113 /* Insert it into the list */
114 InsertHeadList(&MdBlock
->ListEntry
, &FreeBlock
->ListEntry
);
117 /* Use this descriptor */
118 NewBlock
->PageCount
= Alignment
;
119 InsertHeadList(&MdBlock
->ListEntry
, &NewBlock
->ListEntry
);
123 /* Consume memory from this block */
124 MdBlock
->BasePage
+= PageCount
;
125 MdBlock
->PageCount
-= PageCount
;
127 /* Insert the descriptor */
128 InsertTailList(&MdBlock
->ListEntry
, &NewBlock
->ListEntry
);
130 /* Remove the entry if the whole block was allocated */
131 if (!MdBlock
->PageCount
== 0) RemoveEntryList(&MdBlock
->ListEntry
);
134 /* Return the address */
135 return PhysicalAddress
;
140 HalpMapPhysicalMemory64(IN PHYSICAL_ADDRESS PhysicalAddress
,
143 PHARDWARE_PTE PointerPte
;
145 PVOID VirtualAddress
, BaseAddress
;
147 /* Start at the current HAL heap base */
148 BaseAddress
= HalpHeapStart
;
149 VirtualAddress
= BaseAddress
;
151 /* Loop until we have all the pages required */
152 while (UsedPages
< PageCount
)
154 /* If this overflows past the HAL heap, it means there's no space */
155 if (VirtualAddress
== NULL
) return NULL
;
157 /* Get the PTE for this address */
158 PointerPte
= HalAddressToPte(VirtualAddress
);
160 /* Go to the next page */
161 VirtualAddress
= (PVOID
)((ULONG_PTR
)VirtualAddress
+ PAGE_SIZE
);
163 /* Check if the page is available */
164 if (PointerPte
->Valid
)
166 /* PTE has data, skip it and start with a new base address */
167 BaseAddress
= VirtualAddress
;
172 /* PTE is available, keep going on this run */
176 /* Take the base address of the page plus the actual offset in the address */
177 VirtualAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
+
178 BYTE_OFFSET(PhysicalAddress
.LowPart
));
180 /* If we are starting at the heap, move the heap */
181 if (BaseAddress
== HalpHeapStart
)
183 /* Past this allocation */
184 HalpHeapStart
= (PVOID
)((ULONG_PTR
)BaseAddress
+ (PageCount
* PAGE_SIZE
));
187 /* Loop pages that can be mapped */
190 /* Fill out the PTE */
191 PointerPte
= HalAddressToPte(BaseAddress
);
192 PointerPte
->PageFrameNumber
= PhysicalAddress
.QuadPart
>> PAGE_SHIFT
;
193 PointerPte
->Valid
= 1;
194 PointerPte
->Write
= 1;
196 /* Move to the next address */
197 PhysicalAddress
.QuadPart
+= PAGE_SIZE
;
198 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
+ PAGE_SIZE
);
201 /* Flush the TLB and return the address */
203 return VirtualAddress
;
208 HalpUnmapVirtualAddress(IN PVOID VirtualAddress
,
211 PHARDWARE_PTE PointerPte
;
214 /* Only accept valid addresses */
215 if (VirtualAddress
< MM_HAL_VA_START
) return;
217 /* Align it down to page size */
218 VirtualAddress
= (PVOID
)((ULONG_PTR
)VirtualAddress
& ~(PAGE_SIZE
- 1));
221 PointerPte
= HalAddressToPte(VirtualAddress
);
222 for (i
= 0; i
< PageCount
; i
++)
224 *(PULONG
)PointerPte
= 0;
231 /* Put the heap back */
232 if (HalpHeapStart
> VirtualAddress
) HalpHeapStart
= VirtualAddress
;