[NTOSKRNL]

- Rewrite MmFindGapBottomUp and MmFindGapTopDown, the old versions were broken and were first checking the address range after the first memory area and only used the area below (above) the first memory are when nothing free was found.
- Fix an ASSERT, that gets triggered now that the memory areas are created at the "right" locations
- Create a memory are for the boot loaded images, which previously could be overwritten happily by new memory areas, which was only prevented by the brokenness of the code
- Fix a few memory regions so that they are correct for amd64 builds as well

svn path=/trunk/; revision=55397
This commit is contained in:
Timo Kreuzer 2012-02-03 20:59:35 +00:00
parent 173b42e7cb
commit 36a816a584
4 changed files with 135 additions and 140 deletions

View file

@ -331,7 +331,7 @@ ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
} }
/* Copy the codepage data in its new location. */ /* Copy the codepage data in its new location. */
ASSERT(SectionBase > MmSystemRangeStart); ASSERT(SectionBase >= MmSystemRangeStart);
RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize); RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
/* Free the previously allocated buffer and set the new location */ /* Free the previously allocated buffer and set the new location */

View file

@ -30,6 +30,7 @@ PULONG MmGetPageDirectory(VOID);
#define PDE_TOP 0xC0300FFF #define PDE_TOP 0xC0300FFF
#define PTE_TOP 0xC03FFFFF #define PTE_TOP 0xC03FFFFF
#define HYPER_SPACE 0xC0400000 #define HYPER_SPACE 0xC0400000
#define HYPER_SPACE_END 0xC07FFFFF
#define PTE_PER_PAGE 0x400 #define PTE_PER_PAGE 0x400

View file

@ -456,78 +456,68 @@ MmFindGapBottomUp(
ULONG_PTR Length, ULONG_PTR Length,
ULONG_PTR Granularity) ULONG_PTR Granularity)
{ {
PVOID LowestAddress = MmGetAddressSpaceOwner(AddressSpace) ? MM_LOWEST_USER_ADDRESS : MmSystemRangeStart; ULONG_PTR LowestAddress, HighestAddress, Candidate;
PVOID HighestAddress = MmGetAddressSpaceOwner(AddressSpace) ? PMEMORY_AREA Root, Node;
MmHighestUserAddress : (PVOID)MAXULONG_PTR;
PVOID AlignedAddress;
PMEMORY_AREA Node;
PMEMORY_AREA FirstNode;
PMEMORY_AREA PreviousNode;
DPRINT("LowestAddress: %p HighestAddress: %p\n", /* Get the margins of the address space */
LowestAddress, HighestAddress); if (MmGetAddressSpaceOwner(AddressSpace) != NULL)
{
LowestAddress = MM_LOWEST_USER_ADDRESS;
HighestAddress = (ULONG_PTR)MmHighestUserAddress;
}
else
{
LowestAddress = (ULONG_PTR)MmSystemRangeStart;
HighestAddress = MAXULONG_PTR;
}
AlignedAddress = MM_ROUND_UP(LowestAddress, Granularity); /* Start with the lowest address */
Candidate = LowestAddress;
/* Special case for empty tree. */ /* Check for overflow */
if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL) if ((Candidate + Length) < Candidate) return NULL;
{
if ((ULONG_PTR)HighestAddress - (ULONG_PTR)AlignedAddress >= Length)
{
DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress);
return AlignedAddress;
}
DPRINT("MmFindGapBottomUp: 0\n");
return 0;
}
/* Go to the node with lowest address in the tree. */ /* Get the root of the address space tree */
FirstNode = Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink); Root = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
/* Traverse the tree from left to right. */ /* Go to the node with lowest address in the tree. */
PreviousNode = Node; Node = Root ? MmIterateFirstNode(Root) : NULL;
for (;;) while (Node && ((ULONG_PTR)Node->EndingAddress < LowestAddress))
{ {
Node = MmIterateNextNode(Node); Node = MmIterateNextNode(Node);
if (Node == NULL) }
break;
AlignedAddress = MM_ROUND_UP(PreviousNode->EndingAddress, Granularity); /* Traverse the tree from low to high addresses */
if (AlignedAddress >= LowestAddress) while (Node && ((ULONG_PTR)Node->EndingAddress < HighestAddress))
{ {
if (Node->StartingAddress > AlignedAddress && /* Check if the memory area fits before the current node */
(ULONG_PTR)Node->StartingAddress - (ULONG_PTR)AlignedAddress >= Length) if ((ULONG_PTR)Node->StartingAddress >= (Candidate + Length))
{ {
DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress); DPRINT("MmFindGapBottomUp: %p\n", Candidate);
ASSERT(AlignedAddress >= LowestAddress); ASSERT(Candidate >= LowestAddress);
return AlignedAddress; return (PVOID)Candidate;
} }
}
PreviousNode = Node;
}
/* Check if there is enough space after the last memory area. */ /* Calculate next possible adress above this node */
AlignedAddress = MM_ROUND_UP(PreviousNode->EndingAddress, Granularity); Candidate = ALIGN_UP_BY((ULONG_PTR)Node->EndingAddress, Granularity);
if ((ULONG_PTR)HighestAddress > (ULONG_PTR)AlignedAddress &&
(ULONG_PTR)HighestAddress - (ULONG_PTR)AlignedAddress >= Length)
{
DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress);
ASSERT(AlignedAddress >= LowestAddress);
return AlignedAddress;
}
/* Check if there is enough space before the first memory area. */ /* Check for overflow */
AlignedAddress = MM_ROUND_UP(LowestAddress, Granularity); if ((Candidate + Length) < (ULONG_PTR)Node->EndingAddress) return NULL;
if (FirstNode->StartingAddress > AlignedAddress &&
(ULONG_PTR)FirstNode->StartingAddress - (ULONG_PTR)AlignedAddress >= Length)
{
DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress);
ASSERT(AlignedAddress >= LowestAddress);
return AlignedAddress;
}
DPRINT("MmFindGapBottomUp: 0\n"); /* Go to the next higher node */
return 0; Node = MmIterateNextNode(Node);
}
/* Check if there is enough space after the last memory area. */
if ((Candidate + Length) <= HighestAddress)
{
DPRINT("MmFindGapBottomUp: %p\n", Candidate);
ASSERT(Candidate >= LowestAddress);
return (PVOID)Candidate;
}
DPRINT("MmFindGapBottomUp: 0\n");
return NULL;
} }
@ -537,81 +527,68 @@ MmFindGapTopDown(
ULONG_PTR Length, ULONG_PTR Length,
ULONG_PTR Granularity) ULONG_PTR Granularity)
{ {
PVOID LowestAddress = MmGetAddressSpaceOwner(AddressSpace) ? MM_LOWEST_USER_ADDRESS : MmSystemRangeStart; ULONG_PTR LowestAddress, HighestAddress, Candidate;
PVOID HighestAddress = MmGetAddressSpaceOwner(AddressSpace) ? PMEMORY_AREA Root, Node;
(PVOID)((ULONG_PTR)MmSystemRangeStart - 1) : (PVOID)MAXULONG_PTR;
PVOID AlignedAddress;
PMEMORY_AREA Node;
PMEMORY_AREA PreviousNode;
DPRINT("LowestAddress: %p HighestAddress: %p\n", /* Get the margins of the address space */
LowestAddress, HighestAddress); if (MmGetAddressSpaceOwner(AddressSpace) != NULL)
{
LowestAddress = (ULONG_PTR)MM_LOWEST_USER_ADDRESS;
HighestAddress = (ULONG_PTR)MmHighestUserAddress;
}
else
{
LowestAddress = (ULONG_PTR)MmSystemRangeStart;
HighestAddress = MAXULONG_PTR;
}
AlignedAddress = MM_ROUND_DOWN((ULONG_PTR)HighestAddress - Length + 1, Granularity); /* Calculate the highest candidate */
Candidate = ALIGN_DOWN_BY(HighestAddress + 1 - Length, Granularity);
/* Check for overflow. */ /* Check for overflow. */
if (AlignedAddress > HighestAddress) if (Candidate > HighestAddress) return NULL;
return NULL;
/* Special case for empty tree. */ /* Get the root of the address space tree */
if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL) Root = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
{
if (AlignedAddress >= LowestAddress)
{
DPRINT("MmFindGapTopDown: %p\n", AlignedAddress);
return AlignedAddress;
}
DPRINT("MmFindGapTopDown: 0\n");
return 0;
}
/* Go to the node with highest address in the tree. */ /* Go to the node with highest address in the tree. */
Node = MmIterateLastNode((PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink); Node = Root ? MmIterateLastNode(Root) : NULL;
while (Node && ((ULONG_PTR)Node->StartingAddress > HighestAddress))
{
Node = MmIteratePrevNode(Node);
}
/* Check if there is enough space after the last memory area. */ /* Traverse the tree from high to low addresses */
if (Node->EndingAddress <= AlignedAddress) while (Node && ((ULONG_PTR)Node->StartingAddress > LowestAddress))
{ {
DPRINT("MmFindGapTopDown: %p\n", AlignedAddress); /* Check if the memory area fits after the current node */
return AlignedAddress; if ((ULONG_PTR)Node->EndingAddress <= Candidate)
} {
DPRINT("MmFindGapTopDown: %p\n", Candidate);
return (PVOID)Candidate;
}
/* Traverse the tree from left to right. */ /* Calculate next possible adress below this node */
PreviousNode = Node; Candidate = ALIGN_DOWN_BY((ULONG_PTR)Node->StartingAddress - Length,
for (;;) Granularity);
{
Node = MmIteratePrevNode(Node);
if (Node == NULL)
break;
AlignedAddress = MM_ROUND_DOWN((ULONG_PTR)PreviousNode->StartingAddress - Length + 1, Granularity); /* Check for overflow. */
if (Candidate > (ULONG_PTR)Node->StartingAddress)
return NULL;
/* Check for overflow. */ /* Go to the next lower node */
if (AlignedAddress > PreviousNode->StartingAddress) Node = MmIteratePrevNode(Node);
return NULL; }
if (Node->EndingAddress <= AlignedAddress) /* Check if the last candidate is inside the given range */
{ if (Candidate >= LowestAddress)
DPRINT("MmFindGapTopDown: %p\n", AlignedAddress); {
return AlignedAddress; DPRINT("MmFindGapTopDown: %p\n", Candidate);
} return (PVOID)Candidate;
}
PreviousNode = Node; DPRINT("MmFindGapTopDown: 0\n");
} return NULL;
AlignedAddress = MM_ROUND_DOWN((ULONG_PTR)PreviousNode->StartingAddress - Length + 1, Granularity);
/* Check for overflow. */
if (AlignedAddress > PreviousNode->StartingAddress)
return NULL;
if (AlignedAddress >= LowestAddress)
{
DPRINT("MmFindGapTopDown: %p\n", AlignedAddress);
return AlignedAddress;
}
DPRINT("MmFindGapTopDown: 0\n");
return 0;
} }
@ -887,7 +864,7 @@ MmCreateMemoryArea(PMMSUPPORT AddressSpace,
ULONG_PTR tmpLength; ULONG_PTR tmpLength;
PMEMORY_AREA MemoryArea; PMEMORY_AREA MemoryArea;
DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %p, " DPRINT("MmCreateMemoryArea(Type 0x%lx, BaseAddress %p, "
"*BaseAddress %p, Length %p, AllocationFlags %x, " "*BaseAddress %p, Length %p, AllocationFlags %x, "
"FixedAddress %x, Result %p)\n", "FixedAddress %x, Result %p)\n",
Type, BaseAddress, *BaseAddress, Length, AllocationFlags, Type, BaseAddress, *BaseAddress, Length, AllocationFlags,
@ -922,6 +899,7 @@ MmCreateMemoryArea(PMMSUPPORT AddressSpace,
if (MmGetAddressSpaceOwner(AddressSpace) && if (MmGetAddressSpaceOwner(AddressSpace) &&
(ULONG_PTR)(*BaseAddress) + tmpLength > (ULONG_PTR)MmSystemRangeStart) (ULONG_PTR)(*BaseAddress) + tmpLength > (ULONG_PTR)MmSystemRangeStart)
{ {
DPRINT("Memory area for user mode address space exceeds MmSystemRangeStart\n");
return STATUS_ACCESS_VIOLATION; return STATUS_ACCESS_VIOLATION;
} }
@ -1026,8 +1004,9 @@ MmDeleteProcessAddressSpace(PEPROCESS Process)
DPRINT("MmDeleteProcessAddressSpace(Process %x (%s))\n", Process, DPRINT("MmDeleteProcessAddressSpace(Process %x (%s))\n", Process,
Process->ImageFileName); Process->ImageFileName);
#ifndef _M_AMD64
RemoveEntryList(&Process->MmProcessLinks); RemoveEntryList(&Process->MmProcessLinks);
#endif
MmLockAddressSpace(&Process->Vm); MmLockAddressSpace(&Process->Vm);
while ((MemoryArea = (PMEMORY_AREA)Process->Vm.WorkingSetExpansionLinks.Flink) != NULL) while ((MemoryArea = (PMEMORY_AREA)Process->Vm.WorkingSetExpansionLinks.Flink) != NULL)

View file

@ -1,4 +1,4 @@
/* /*
* PROJECT: ReactOS Kernel * PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/mm/mminit.c * FILE: ntoskrnl/mm/mminit.c
@ -44,6 +44,21 @@ MiInitSystemMemoryAreas()
NTSTATUS Status; NTSTATUS Status;
BoundaryAddressMultiple.QuadPart = 0; BoundaryAddressMultiple.QuadPart = 0;
//
// Create the memory area to define the loader mappings
//
BaseAddress = (PVOID)KSEG0_BASE;
Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
&BaseAddress,
MmBootImageSize,
PAGE_EXECUTE_READWRITE,
&MArea,
TRUE,
0,
BoundaryAddressMultiple);
ASSERT(Status == STATUS_SUCCESS);
// //
// Create the memory area to define the PTE base // Create the memory area to define the PTE base
// //
@ -51,7 +66,7 @@ MiInitSystemMemoryAreas()
Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
&BaseAddress, &BaseAddress,
4 * 1024 * 1024, PTE_TOP - PTE_BASE + 1,
PAGE_READWRITE, PAGE_READWRITE,
&MArea, &MArea,
TRUE, TRUE,
@ -66,7 +81,7 @@ MiInitSystemMemoryAreas()
Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC,
&BaseAddress, &BaseAddress,
4 * 1024 * 1024, HYPER_SPACE_END - HYPER_SPACE + 1,
PAGE_READWRITE, PAGE_READWRITE,
&MArea, &MArea,
TRUE, TRUE,
@ -165,7 +180,7 @@ MiInitSystemMemoryAreas()
0, 0,
BoundaryAddressMultiple); BoundaryAddressMultiple);
ASSERT(Status == STATUS_SUCCESS); ASSERT(Status == STATUS_SUCCESS);
#ifndef _M_AMD64
// //
// Next, the KPCR // Next, the KPCR
// //
@ -180,7 +195,7 @@ MiInitSystemMemoryAreas()
0, 0,
BoundaryAddressMultiple); BoundaryAddressMultiple);
ASSERT(Status == STATUS_SUCCESS); ASSERT(Status == STATUS_SUCCESS);
#endif
// //
// Now the KUSER_SHARED_DATA // Now the KUSER_SHARED_DATA
// //
@ -238,8 +253,8 @@ MiDbgDumpAddressSpace(VOID)
// Print the memory layout // Print the memory layout
// //
DPRINT1(" 0x%p - 0x%p\t%s\n", DPRINT1(" 0x%p - 0x%p\t%s\n",
MmSystemRangeStart, KSEG0_BASE,
(ULONG_PTR)MmSystemRangeStart + MmBootImageSize, (ULONG_PTR)KSEG0_BASE + MmBootImageSize,
"Boot Loaded Image"); "Boot Loaded Image");
DPRINT1(" 0x%p - 0x%p\t%s\n", DPRINT1(" 0x%p - 0x%p\t%s\n",
MmPfnDatabase, MmPfnDatabase,
@ -258,13 +273,13 @@ MiDbgDumpAddressSpace(VOID)
MiSessionSpaceEnd, MiSessionSpaceEnd,
"Session Space"); "Session Space");
DPRINT1(" 0x%p - 0x%p\t%s\n", DPRINT1(" 0x%p - 0x%p\t%s\n",
PTE_BASE, PDE_BASE, PTE_BASE, PTE_TOP,
"Page Tables"); "Page Tables");
DPRINT1(" 0x%p - 0x%p\t%s\n", DPRINT1(" 0x%p - 0x%p\t%s\n",
PDE_BASE, HYPER_SPACE, PDE_BASE, PDE_TOP,
"Page Directories"); "Page Directories");
DPRINT1(" 0x%p - 0x%p\t%s\n", DPRINT1(" 0x%p - 0x%p\t%s\n",
HYPER_SPACE, HYPER_SPACE + (4 * 1024 * 1024), HYPER_SPACE, HYPER_SPACE_END,
"Hyperspace"); "Hyperspace");
DPRINT1(" 0x%p - 0x%p\t%s\n", DPRINT1(" 0x%p - 0x%p\t%s\n",
MmPagedPoolStart, MmPagedPoolStart,