[BOOT:MM] Big work on MM :)

This commit is contained in:
2024-08-27 09:32:16 -04:00
parent 6a868b45ba
commit 2751b0f7bb
7 changed files with 930 additions and 29 deletions

View File

@@ -32,11 +32,11 @@ Routine Description:
Arguments:
MemoryInfo - pointer to the memory info structure.
MemoryInfo - Pointer to the memory info.
TranslationType - the current translation type being used.
TranslationType - The current translation type.
LibraryParameters - pointer to the library parameters structure.
LibraryParameters - Pointer to the library parameters.
Return Value:

View File

@@ -22,10 +22,316 @@ Abstract:
MEMORY_DESCRIPTOR MmStaticMemoryDescriptors[MAX_STATIC_DESCRIPTOR_COUNT];
PMEMORY_DESCRIPTOR MmGlobalMemoryDescriptors;
ULONG MmGlobalMemoryDescriptorCount;
ULONG MmGlobalMemoryDescriptorCount, MmGlobalMemoryDescriptorsUsed;
PMEMORY_DESCRIPTOR MmDynamicMemoryDescriptors;
ULONG MmDynamicMemoryDescriptorCount;
ULONG MmDynamicMemoryDescriptorCount, MmDynamicMemoryDescriptorsUsed;
BOOLEAN
MmMdpHasPrecedence (
IN MEMORY_TYPE A,
IN MEMORY_TYPE B
)
/*++
Routine Description:
Compares two memory types to determine which has precedence.
Arguments:
A - memory type A.
B - memory type B.
Return Value:
TRUE if A has precedence over B, or if neither has precedence.
FALSE if B has precedence over A.
--*/
{
ULONG ClassA, ClassB;
ClassA = A >> 28;
ClassB = B >> 28;
if (B == MEMORY_TYPE_FREE) {
return TRUE;
}
if (A == MEMORY_TYPE_FREE) {
return FALSE;
}
if (ClassA > 0x0F) {
return TRUE;
}
if (ClassB > 0x0F) {
return FALSE;
}
if (ClassA != 0x0F) {
return (ClassB != 0x0F && (ClassA == 0x0D || ClassB != 0x0D)) ? TRUE:FALSE;
}
if (ClassB != 0x0F) {
return TRUE;
}
//
// TODO: Incomplete.
//
ConsolePrint(L"MmMdpHasPrecedence() is incomplete\r\n");
return TRUE;
}
BOOLEAN
MmMdpTruncateDescriptor (
IN PMEMORY_DESCRIPTOR_LIST Mdl,
IN PMEMORY_DESCRIPTOR Descriptor,
IN ULONG Flags
)
/*++
Routine Description:
Trunactes a memory descriptor that overlaps
with adjacent descriptors.
Arguments:
Mdl - The MDL containing Descriptor.
Descriptor - The descriptor to truncate.
Return Value:
TRUE if Descriptor was deleted from Mdl.
--*/
{
PMEMORY_DESCRIPTOR PrevDescriptor, NextDescriptor, NewDescriptor;
ULONGLONG DescriptorEnd, PrevDescriptorEnd, NextDescriptorEnd;
ULONGLONG MappedFirstPage;
ULONGLONG Change;
PrevDescriptor = (PMEMORY_DESCRIPTOR)Descriptor->ListEntry.Blink;
NextDescriptor = (PMEMORY_DESCRIPTOR)Descriptor->ListEntry.Flink;
DescriptorEnd = Descriptor->FirstPage + Descriptor->PageCount;
PrevDescriptorEnd = PrevDescriptor->FirstPage + PrevDescriptor->PageCount;
NextDescriptorEnd = NextDescriptor->FirstPage + NextDescriptor->PageCount;
//
// Check if overlapping with previous descriptor.
//
if (Descriptor->ListEntry.Blink != Mdl->Head && Descriptor->FirstPage < PrevDescriptorEnd) {
if (MmMdpHasPrecedence(Descriptor->Type, PrevDescriptor->Type)) {
PrevDescriptor->PageCount = Descriptor->FirstPage - PrevDescriptor->FirstPage;
if (DescriptorEnd < PrevDescriptorEnd) {
if (PrevDescriptor->MappedFirstPage) {
MappedFirstPage = PrevDescriptor->MappedFirstPage + DescriptorEnd - PrevDescriptor->FirstPage;
} else {
MappedFirstPage = 0;
}
NewDescriptor = MmMdInitDescriptor(
DescriptorEnd,
MappedFirstPage,
PrevDescriptorEnd - DescriptorEnd,
PrevDescriptor->Attributes,
PrevDescriptor->Type
);
if (NewDescriptor != NULL) {
MmMdAddDescriptorToList(Mdl, NewDescriptor, Flags);
}
}
//
// Delete and free the previous
// descriptor if it is now empty.
//
if (PrevDescriptor->PageCount == 0) {
MmMdRemoveDescriptorFromList(Mdl, PrevDescriptor);
MmMdFreeDescriptor(PrevDescriptor);
}
} else {
//
// Remove if completely overlapping.
//
if (DescriptorEnd <= PrevDescriptorEnd) {
MmMdRemoveDescriptorFromList(Mdl, Descriptor);
MmMdFreeDescriptor(Descriptor);
return TRUE;
}
//
// Otherwise, move the descriptor.
//
Change = PrevDescriptorEnd - Descriptor->FirstPage;
Descriptor->FirstPage += Change;
Descriptor->PageCount -= Change;
if (Descriptor->MappedFirstPage) {
Descriptor->MappedFirstPage += Change;
}
}
}
//
// Check if overlapping with next descriptor.
//
if (Descriptor->ListEntry.Flink != Mdl->Head && NextDescriptor->FirstPage < DescriptorEnd) {
if (MmMdpHasPrecedence(NextDescriptor->Type, Descriptor->Type)) {
Descriptor->PageCount = NextDescriptor->FirstPage - Descriptor->FirstPage;
if (NextDescriptorEnd < DescriptorEnd) {
if (Descriptor->MappedFirstPage) {
MappedFirstPage = Descriptor->MappedFirstPage + NextDescriptorEnd - Descriptor->FirstPage;
} else {
MappedFirstPage = 0;
}
NewDescriptor = MmMdInitDescriptor(
NextDescriptorEnd,
MappedFirstPage,
DescriptorEnd - NextDescriptorEnd,
Descriptor->Attributes,
Descriptor->Type
);
if (NewDescriptor != NULL) {
MmMdAddDescriptorToList(Mdl, NewDescriptor, Flags);
}
}
//
// Delete and free the previous
// descriptor if it is now empty.
//
if (Descriptor->PageCount == 0) {
MmMdRemoveDescriptorFromList(Mdl, Descriptor);
MmMdFreeDescriptor(Descriptor);
}
} else {
//
// Remove if completely overlapping.
//
if (NextDescriptorEnd <= DescriptorEnd) {
MmMdRemoveDescriptorFromList(Mdl, NextDescriptor);
MmMdFreeDescriptor(NextDescriptor);
return TRUE;
}
//
// Otherwise, move the next descriptor.
//
Change = DescriptorEnd - NextDescriptor->FirstPage;
NextDescriptor->FirstPage += Change;
NextDescriptor->PageCount -= Change;
if (NextDescriptor->MappedFirstPage) {
NextDescriptor->MappedFirstPage += Change;
}
}
}
return FALSE;
}
NTSTATUS
MmMdAddDescriptorToList (
IN PMEMORY_DESCRIPTOR_LIST Mdl,
IN PMEMORY_DESCRIPTOR Descriptor,
IN ULONG Flags
)
/*++
Routine Description:
Adds a descriptor to a MDL.
Arguments:
Mdl - the MDL to add Descriptor to.
Descriptor - the descriptor to add to Mdl.
Return Value:
STATUS_SUCCESS if successful,
STATUS_INVALID_PARAMETER if Mdl or Descriptor are invalid.
--*/
{
PLIST_ENTRY Entry;
PMEMORY_DESCRIPTOR CurrentDescriptor;
if (Mdl == NULL || Descriptor == NULL) {
return STATUS_INVALID_PARAMETER;
}
if (Mdl->Current) {
if (Descriptor->FirstPage < ((PMEMORY_DESCRIPTOR)Mdl->Current)->FirstPage) {
Entry = Mdl->Head->Flink;
} else {
Entry = Mdl->Current;
}
} else {
Entry = Mdl->Head->Flink;
}
//
// Search for an existing descriptor for this region.
//
while (Entry != Mdl->Head) {
CurrentDescriptor = (PMEMORY_DESCRIPTOR)Entry;
if (
Descriptor->FirstPage >= CurrentDescriptor->FirstPage && (Descriptor->FirstPage != CurrentDescriptor->FirstPage
|| !MmMdpHasPrecedence(Descriptor->Type, CurrentDescriptor->Type))
) {
Entry = Entry->Flink;
continue;
}
//
// Insert descriptor into the list
// right before the current entry.
//
Descriptor->ListEntry.Blink = Entry->Blink;
Descriptor->ListEntry.Flink = Entry;
Entry->Blink->Flink = &Descriptor->ListEntry;
Entry->Blink = &Descriptor->ListEntry;
//
// Truncate overlapping descriptors
// into one larger descriptor.
//
if (Flags & MDL_OPERATION_FLAGS_TRUNCATE) {
MmMdpTruncateDescriptor(Mdl, Descriptor, Flags);
}
return STATUS_SUCCESS;
}
//
// If there are no existing descriptors for this region
// (or the list is empty), insert and truncate the descriptor.
//
InsertTailList(Mdl->Head, &Descriptor->ListEntry);
if (Flags & MDL_OPERATION_FLAGS_TRUNCATE) {
MmMdpTruncateDescriptor(Mdl, Descriptor, Flags);
}
return STATUS_SUCCESS;
}
VOID
MmMdRemoveDescriptorFromList (
@@ -55,10 +361,6 @@ Return Value:
PLIST_ENTRY Blink;
Blink = Descriptor->ListEntry.Blink;
//
// Remove the descriptor from the MDL.
//
RemoveEntryList(&Descriptor->ListEntry);
//
@@ -129,7 +431,7 @@ Return Value:
// Free the descriptor from the heap.
// TODO: Use BlMmFreeHeap()
//
ConsolePrint(L"Cannot free memory descriptor: BlMmFreeHeap() is not implemented\r\n");
ConsolePrint(L"MmMdFreeDescriptor(): need BlMmFreeHeap() to free descriptor\r\n");
return STATUS_NOT_IMPLEMENTED;
// return BlMmFreeHeap(Descriptor);
}
@@ -147,7 +449,7 @@ Routine Description:
Arguments:
Mdl - the MDL to free.
Mdl - the MDL.
Return Value:
@@ -166,6 +468,56 @@ Return Value:
}
}
PMEMORY_DESCRIPTOR
MmMdInitDescriptor (
IN ULONGLONG FirstPage,
IN ULONGLONG MappedFirstPage,
IN ULONGLONG PageCount,
IN ULONG Attributes,
IN MEMORY_TYPE Type
)
/*++
Routine Description:
Initializes a memory descriptor.
Arguments:
FirstPage - The first page in the region.
MappedFirstPage - The first page in the mapping.
Attributes - Memory attributes of the region.
Type - Memory type of the region.
Return Value:
Pointer to the memory descriptor,
NULL if an error occurs.
--*/
{
PMEMORY_DESCRIPTOR Descriptor;
if (MmGlobalMemoryDescriptorsUsed >= MmGlobalMemoryDescriptorCount) {
return NULL;
}
Descriptor = &MmGlobalMemoryDescriptors[MmGlobalMemoryDescriptorsUsed++];
Descriptor->FirstPage = FirstPage;
Descriptor->MappedFirstPage = MappedFirstPage;
Descriptor->PageCount = PageCount;
Descriptor->Attributes = Attributes;
Descriptor->Type = Type;
InitializeListHead(&Descriptor->ListEntry);
return Descriptor;
}
VOID
MmMdInitialize (
IN ULONG Unused,
@@ -201,6 +553,7 @@ Return Value:
//
MmGlobalMemoryDescriptors = &MmStaticMemoryDescriptors[0];
MmGlobalMemoryDescriptorCount = MAX_STATIC_DESCRIPTOR_COUNT;
MmGlobalMemoryDescriptorsUsed = 0;
RtlZeroMemory(MmGlobalMemoryDescriptors, MAX_STATIC_DESCRIPTOR_COUNT * sizeof(MEMORY_DESCRIPTOR));
DebugPrintf(L"Global memory descriptor count: %x\r\n", MmGlobalMemoryDescriptorCount);
}

View File

@@ -44,7 +44,7 @@ Routine Description:
Arguments:
Mdl - the MDL to initialize.
Mdl - Pointer to the MDL.
Return Value:
@@ -72,9 +72,9 @@ Routine Description:
Arguments:
MemoryInfo - pointer to the memory info structure.
MemoryInfo - Pointer to the memory info structure.
MinimumAllocation - minimum amount of pages to grow the pool by at a time.
MinimumAllocation - Minimum amount of pages to grow the pool by at a time.
Return Value: