From 53b637ba7e7f0ee77447298516b286a1c9b4dac4 Mon Sep 17 00:00:00 2001 From: Sir Richard Date: Wed, 31 Mar 2010 04:38:20 +0000 Subject: [PATCH] [HAL]: Add Phase 0 HAL Heap Allocation/Mapping/Unmapping APIs, remove current broken APIs that depend on Mm having been initialized. These APIs use the HAL Heap that's typically at 0xFFC00000. FreeLDR seems to map this region correctly. [HAL]: Although currently implemented for ACPI support (to come), these APIs can now also be used to enable DMA in Phase 0 like NT, instead of only in Phase 1 like ReactOS. svn path=/trunk/; revision=46612 --- reactos/hal/halx86/generic/halinit.c | 215 +++++++++++++++++++++++++++ reactos/hal/halx86/generic/misc.c | 26 ---- reactos/hal/halx86/include/halp.h | 16 +- 3 files changed, 230 insertions(+), 27 deletions(-) diff --git a/reactos/hal/halx86/generic/halinit.c b/reactos/hal/halx86/generic/halinit.c index 498bf5cc5bb..8704b398c91 100644 --- a/reactos/hal/halx86/generic/halinit.c +++ b/reactos/hal/halx86/generic/halinit.c @@ -14,10 +14,225 @@ /* GLOBALS *******************************************************************/ +/* Share with Mm headers? */ +#define MM_HAL_VA_START (PVOID)0xFFC00000 +#define MM_HAL_HEAP_START (PVOID)((ULONG_PTR)MM_HAL_VA_START + (1024 * 1024)) + BOOLEAN HalpPciLockSettings; +ULONG HalpUsedAllocDescriptors; +MEMORY_ALLOCATION_DESCRIPTOR HalpAllocationDescriptorArray[64]; +PVOID HalpHeapStart = MM_HAL_HEAP_START; /* PRIVATE FUNCTIONS *********************************************************/ +ULONG +NTAPI +HalpAllocPhysicalMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN ULONG MaxAddress, + IN ULONG PageCount, + IN BOOLEAN Aligned) +{ + ULONG UsedDescriptors, Alignment, PhysicalAddress; + PFN_NUMBER MaxPage, BasePage; + PLIST_ENTRY NextEntry; + PMEMORY_ALLOCATION_DESCRIPTOR MdBlock, NewBlock, FreeBlock; + + /* Highest page we'll go */ + MaxPage = MaxAddress >> PAGE_SHIFT; + + /* We need at least two blocks */ + if ((HalpUsedAllocDescriptors + 2) > 64) return 0; + + /* Remember how many we have now */ + UsedDescriptors = HalpUsedAllocDescriptors; + + /* Loop the loader block memory descriptors */ + NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink; + while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) + { + /* Get the block */ + MdBlock = CONTAINING_RECORD(NextEntry, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + + /* No alignment by default */ + Alignment = 0; + + /* Unless requested, in which case we use a 64KB block alignment */ + if (Aligned) Alignment = ((MdBlock->BasePage + 0x0F) & ~0x0F) - MdBlock->BasePage; + + /* Search for free memory */ + if ((MdBlock->MemoryType == LoaderFree) || + (MdBlock->MemoryType == MemoryFirmwareTemporary)) + { + /* Make sure the page is within bounds, including alignment */ + BasePage = MdBlock->BasePage; + if ((BasePage) && + (MdBlock->PageCount >= PageCount + Alignment) && + (BasePage + PageCount + Alignment < MaxPage)) + { + + /* We found an address */ + PhysicalAddress = (BasePage + Alignment) << PAGE_SHIFT; + break; + } + } + + /* Keep trying */ + NextEntry = NextEntry->Flink; + } + + /* If we didn't find anything, get out of here */ + if (NextEntry == &LoaderBlock->MemoryDescriptorListHead) return 0; + + /* Okay, now get a descriptor */ + NewBlock = &HalpAllocationDescriptorArray[HalpUsedAllocDescriptors]; + NewBlock->PageCount = PageCount; + NewBlock->BasePage = MdBlock->BasePage + Alignment; + NewBlock->MemoryType = LoaderHALCachedMemory; + + /* Update count */ + UsedDescriptors++; + HalpUsedAllocDescriptors = UsedDescriptors; + + /* Check if we had any alignment */ + if (Alignment) + { + /* Check if we had leftovers */ + if ((MdBlock->PageCount - Alignment) != PageCount) + { + /* Get the next descriptor */ + FreeBlock = &HalpAllocationDescriptorArray[UsedDescriptors]; + FreeBlock->PageCount = MdBlock->PageCount - Alignment - PageCount; + FreeBlock->BasePage = MdBlock->BasePage + Alignment + PageCount; + + /* One more */ + HalpUsedAllocDescriptors++; + + /* Insert it into the list */ + InsertHeadList(&MdBlock->ListEntry, &FreeBlock->ListEntry); + } + + /* Use this descriptor */ + NewBlock->PageCount = Alignment; + InsertHeadList(&MdBlock->ListEntry, &NewBlock->ListEntry); + } + else + { + /* Consume memory from this block */ + MdBlock->BasePage += PageCount; + MdBlock->PageCount -= PageCount; + + /* Insert the descriptor */ + InsertTailList(&MdBlock->ListEntry, &NewBlock->ListEntry); + + /* Remove the entry if the whole block was allocated */ + if (!MdBlock->PageCount == 0) RemoveEntryList(&MdBlock->ListEntry); + } + + /* Return the address */ + return PhysicalAddress; +} + +PVOID +NTAPI +HalpMapPhysicalMemory64(IN PHYSICAL_ADDRESS PhysicalAddress, + IN ULONG PageCount) +{ + PHARDWARE_PTE PointerPte; + ULONG UsedPages = 0; + PVOID VirtualAddress, BaseAddress; + + /* Start at the current HAL heap base */ + BaseAddress = HalpHeapStart; + + /* Loop until we have all the pages required */ + while (UsedPages < PageCount) + { + /* Begin a new loop cycle */ + UsedPages = 0; + VirtualAddress = BaseAddress; + + /* If this overflows past the HAL heap, it means there's no space */ + if (BaseAddress == NULL) return NULL; + + /* Loop until we have all the pages required in a single run */ + while (UsedPages < PageCount) + { + /* Get the PTE for this address and check if it's available */ + PointerPte = HalAddressToPte(VirtualAddress); + if (*(PULONG)PointerPte) + { + /* PTE has data, skip it and start with a new base address */ + BaseAddress = (PVOID)((ULONG_PTR)VirtualAddress + PAGE_SIZE); + break; + } + + /* PTE is available, keep going on this run */ + VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress + PAGE_SIZE); + UsedPages++; + } + } + + /* Take the base address of the page plus the actual offset in the address */ + VirtualAddress = (PVOID)((ULONG_PTR)BaseAddress + + BYTE_OFFSET(PhysicalAddress.LowPart)); + + /* If we are starting at the heap, move the heap */ + if (BaseAddress == HalpHeapStart) + { + /* Past this allocation */ + HalpHeapStart = (PVOID)((ULONG_PTR)BaseAddress + (PageCount * PAGE_SIZE)); + } + + /* Loop pages that can be mapped */ + while (UsedPages--) + { + /* Fill out the PTE */ + PointerPte = HalAddressToPte(BaseAddress); + PointerPte->PageFrameNumber = PhysicalAddress.QuadPart >> PAGE_SHIFT; + PointerPte->Valid = 1; + PointerPte->Write = 1; + + /* Move to the next address */ + PhysicalAddress.QuadPart += PAGE_SIZE; + BaseAddress = (PVOID)((ULONG_PTR)BaseAddress + PAGE_SIZE); + } + + /* Flush the TLB and return the address */ + HalpFlushTLB(); + return VirtualAddress; +} + +VOID +NTAPI +HalpUnmapVirtualAddress(IN PVOID VirtualAddress, + IN ULONG PageCount) +{ + PHARDWARE_PTE PointerPte; + ULONG i; + + /* Only accept valid addresses */ + if (VirtualAddress < MM_HAL_VA_START) return; + + /* Align it down to page size */ + VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress & ~(PAGE_SIZE - 1)); + + /* Loop PTEs */ + PointerPte = HalAddressToPte(VirtualAddress); + for (i = 0; i < PageCount; i++) + { + *(PULONG)PointerPte = 0; + PointerPte++; + } + + /* Flush the TLB */ + HalpFlushTLB(); + + /* Put the heap back */ + if (HalpHeapStart > VirtualAddress) HalpHeapStart = VirtualAddress; +} + VOID NTAPI HalpGetParameters(IN PLOADER_PARAMETER_BLOCK LoaderBlock) diff --git a/reactos/hal/halx86/generic/misc.c b/reactos/hal/halx86/generic/misc.c index 4ddd30ee589..f778b172d3e 100644 --- a/reactos/hal/halx86/generic/misc.c +++ b/reactos/hal/halx86/generic/misc.c @@ -28,32 +28,6 @@ HalpCheckPowerButton(VOID) return; } -#ifndef _MINIHAL_ -PVOID -NTAPI -HalpMapPhysicalMemory64(IN PHYSICAL_ADDRESS PhysicalAddress, - IN ULONG NumberPage) -{ - // - // Use kernel memory manager I/O map facilities - // - return MmMapIoSpace(PhysicalAddress, - NumberPage << PAGE_SHIFT, - MmNonCached); -} - -VOID -NTAPI -HalpUnmapVirtualAddress(IN PVOID VirtualAddress, - IN ULONG NumberPages) -{ - // - // Use kernel memory manager I/O map facilities - // - MmUnmapIoSpace(VirtualAddress, NumberPages << PAGE_SHIFT); -} -#endif - VOID NTAPI HalpFlushTLB(VOID) diff --git a/reactos/hal/halx86/include/halp.h b/reactos/hal/halx86/include/halp.h index 6fd63fa3e17..6ded9513258 100644 --- a/reactos/hal/halx86/include/halp.h +++ b/reactos/hal/halx86/include/halp.h @@ -681,7 +681,21 @@ HalpReleaseCmosSpinLock( VOID ); - +ULONG +NTAPI +HalpAllocPhysicalMemory( + IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN ULONG MaxAddress, + IN ULONG PageCount, + IN BOOLEAN Aligned +); + +PVOID +NTAPI +HalpMapPhysicalMemory64( + IN PHYSICAL_ADDRESS PhysicalAddress, + IN ULONG PageCount +); VOID FASTCALL -- 2.17.1