https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6da93539a96b2ad1c59350a9e50c665901b7b5cd
commit 6da93539a96b2ad1c59350a9e50c665901b7b5cd Author: Timo Kreuzer <timo.kreu...@reactos.org> AuthorDate: Sat Aug 18 12:16:33 2018 +0200 Commit: GitHub <nore...@github.com> CommitDate: Sat Aug 18 12:16:33 2018 +0200 [FREELDR] Fix calculation of page lookup table (#761) On x64 we only map 1GB of pages, so adjust MM_MAX_PAGE accordingly and also respect that value when searching for the best location of the page lookup table. CORE-11048 #resolve --- boot/freeldr/freeldr/include/mm.h | 3 +-- boot/freeldr/freeldr/lib/mm/meminit.c | 30 +++++++++++++++++++----------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/boot/freeldr/freeldr/include/mm.h b/boot/freeldr/freeldr/include/mm.h index d29fe6087f..adc13d0ebf 100644 --- a/boot/freeldr/freeldr/include/mm.h +++ b/boot/freeldr/freeldr/include/mm.h @@ -58,8 +58,7 @@ typedef struct _FREELDR_MEMORY_DESCRIPTOR #define MM_PAGE_SIZE 4096 #define MM_PAGE_MASK 0xFFF #define MM_PAGE_SHIFT 12 -// FIXME: freeldr implementation uses ULONG for page numbers -#define MM_MAX_PAGE 0xFFFFFFFFFFFFF +#define MM_MAX_PAGE 0x3FFFF /* freeldr only maps 1 GB */ #define MM_SIZE_TO_PAGES(a) \ ( ((a) >> MM_PAGE_SHIFT) + ((a) & MM_PAGE_MASK ? 1 : 0) ) diff --git a/boot/freeldr/freeldr/lib/mm/meminit.c b/boot/freeldr/freeldr/lib/mm/meminit.c index bbf7a571fe..164236c81c 100644 --- a/boot/freeldr/freeldr/lib/mm/meminit.c +++ b/boot/freeldr/freeldr/lib/mm/meminit.c @@ -415,13 +415,15 @@ PVOID MmFindLocationForPageLookupTable(PFN_NUMBER TotalPageCount) { const FREELDR_MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; SIZE_T PageLookupTableSize; - PFN_NUMBER PageLookupTablePages; - PFN_NUMBER PageLookupTableStartPage = 0; + PFN_NUMBER RequiredPages; + PFN_NUMBER CandidateBasePage = 0; + PFN_NUMBER CandidatePageCount; + PFN_NUMBER PageLookupTableEndPage; PVOID PageLookupTableMemAddress = NULL; // Calculate how much pages we need to keep the page lookup table PageLookupTableSize = TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM); - PageLookupTablePages = PageLookupTableSize / MM_PAGE_SIZE; + RequiredPages = PageLookupTableSize / MM_PAGE_SIZE; // Search the highest memory block big enough to contain lookup table while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL) @@ -429,22 +431,28 @@ PVOID MmFindLocationForPageLookupTable(PFN_NUMBER TotalPageCount) // Continue, if memory is not free if (MemoryDescriptor->MemoryType != LoaderFree) continue; - // Continue, if the block is not big enough? - if (MemoryDescriptor->PageCount < PageLookupTablePages) continue; + // Continue, if the block is not big enough + if (MemoryDescriptor->PageCount < RequiredPages) continue; // Continue, if it is not at a higher address than previous address - if (MemoryDescriptor->BasePage < PageLookupTableStartPage) continue; + if (MemoryDescriptor->BasePage < CandidateBasePage) continue; // Continue, if the address is too high - if (MemoryDescriptor->BasePage >= MM_MAX_PAGE) continue; + if (MemoryDescriptor->BasePage + RequiredPages >= MM_MAX_PAGE) continue; // Memory block is more suitable than the previous one - PageLookupTableStartPage = MemoryDescriptor->BasePage; - PageLookupTableMemAddress = (PVOID)((ULONG_PTR) - (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) * MM_PAGE_SIZE - - PageLookupTableSize); + CandidateBasePage = MemoryDescriptor->BasePage; + CandidatePageCount = MemoryDescriptor->PageCount; } + // Calculate the end address for the lookup table + PageLookupTableEndPage = min(CandidateBasePage + CandidatePageCount, + MM_MAX_PAGE); + + // Calculate the virtual address + PageLookupTableMemAddress = (PVOID)((PageLookupTableEndPage * PAGE_SIZE) + - PageLookupTableSize); + TRACE("MmFindLocationForPageLookupTable() returning 0x%x\n", PageLookupTableMemAddress); return PageLookupTableMemAddress;