Author: ion Date: Sun Sep 6 20:55:50 2015 New Revision: 69071
URL: http://svn.reactos.org/svn/reactos?rev=69071&view=rev Log: [BOOTMGFW] - Fix some heap bugs. It (works?) now, at least for one allocation. - Fix GCC support for Phase 1 Architectural Initialization. - Implement Time measurement for Hyper-V compatible hypervisors (tested with Virtual Box 5.0!) as well as non-hypervisors (also tested)
Added: trunk/reactos/boot/environ/lib/platform/time.c (with props) Modified: trunk/reactos/boot/environ/CMakeLists.txt trunk/reactos/boot/environ/include/bl.h trunk/reactos/boot/environ/lib/arch/i386/arch.c trunk/reactos/boot/environ/lib/bootlib.c trunk/reactos/boot/environ/lib/firmware/efi/firmware.c trunk/reactos/boot/environ/lib/mm/heapalloc.c
Modified: trunk/reactos/boot/environ/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/CMakeLists.txt... ============================================================================== --- trunk/reactos/boot/environ/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/boot/environ/CMakeLists.txt [iso-8859-1] Sun Sep 6 20:55:50 2015 @@ -17,7 +17,8 @@ lib/mm/pagealloc.c lib/mm/heapalloc.c lib/mm/blkalloc.c - lib/mm/descriptor.c) + lib/mm/descriptor.c + lib/platform/time.c)
if(ARCH STREQUAL "i386") list(APPEND BOOTLIB_ASM_SOURCE
Modified: trunk/reactos/boot/environ/include/bl.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/include/bl.h?r... ============================================================================== --- trunk/reactos/boot/environ/include/bl.h [iso-8859-1] (original) +++ trunk/reactos/boot/environ/include/bl.h [iso-8859-1] Sun Sep 6 20:55:50 2015 @@ -522,6 +522,18 @@ _Inout_ EFI_PHYSICAL_ADDRESS* Memory );
+NTSTATUS +EfiStall ( + _In_ ULONG StallTime + ); + +/* PLATFORM TIMER ROUTINES ***************************************************/ + +NTSTATUS +BlpTimeCalibratePerformanceCounter ( + VOID + ); + /* UTILITY ROUTINES **********************************************************/
EFI_STATUS
Modified: trunk/reactos/boot/environ/lib/arch/i386/arch.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/arch/i386/... ============================================================================== --- trunk/reactos/boot/environ/lib/arch/i386/arch.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/arch/i386/arch.c [iso-8859-1] Sun Sep 6 20:55:50 2015 @@ -19,13 +19,20 @@ /* FUNCTIONS *****************************************************************/
VOID -//__declspec(naked) fixme: gcc +DECLSPEC_NORETURN ArchTrapNoProcess ( VOID ) { /* Do nothing, this is an unsupported debugging interrupt */ - // _asm { iret } FIXME: GCC +#if defined(__GNUC__) + __asm__ __volatile__ ("iret"); +#elif defined (_MSC_VER) + _asm { iret }; +#else +#error wtf are you using +#endif + __assume(0); }
VOID @@ -208,8 +215,13 @@ IdtBase = (PKIDTENTRY)Idtr.Base;
/* Get the Code Segment */ - // _asm { mov CodeSegment, cs } FIXME: GCC - CodeSegment = 8; // fix fix +#if defined(__GNUC__) + __asm__ __volatile__ ("mov %%cs,%0\n\t" :"=r" (CodeSegment)); +#elif defined (_MSC_VER) + _asm { mov CodeSegment, cs }; +#else +#error wtf are you using +#endif
/* Set up INT 3, ASSERT, and SECURITY_ASSERT to be no-op (for Rtl) */ IdtBase[3].Offset = (USHORT)(ULONG_PTR)ArchTrapNoProcess; @@ -230,7 +242,13 @@ __lidt(&Idtr);
/* Reset FPU state */ - // __asm { fninit } FIXME: GCC +#if defined(__GNUC__) + __asm__ __volatile__ ("fninit"); +#elif defined (_MSC_VER) + _asm { fninit }; +#else +#error wtf are you using +#endif } else {
Modified: trunk/reactos/boot/environ/lib/bootlib.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/bootlib.c?... ============================================================================== --- trunk/reactos/boot/environ/lib/bootlib.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/bootlib.c [iso-8859-1] Sun Sep 6 20:55:50 2015 @@ -132,6 +132,50 @@ goto Quickie; }
+ /* Initialize firmware now that the heap, etc works */ + Status = BlpFwInitialize(1, FirmwareDescriptor); + if (!NT_SUCCESS(Status)) + { + /* Destroy memory manager in phase 1 */ + //BlpMmDestroy(1); + EarlyPrint(L"Firmware2 init failed!\n"); + return Status; + } + +#if 0 + /* Modern systems have an undocumented BCD system for the boot frequency */ + Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData, + 0x15000075, + &BootFrequency); + if (NT_SUCCESS(Status) && (BootFrequency)) + { + /* Use it if present */ + BlpTimePerformanceFrequency = BootFrequency; + } + else +#endif + { + /* Use the TSC for calibration */ + Status = BlpTimeCalibratePerformanceCounter(); + if (!NT_SUCCESS(Status)) + { + /* Destroy memory manager in phase 1 */ + EarlyPrint(L"TSC calibration failed\n"); + //BlpMmDestroy(1); + return Status; + } + } + + /* Now setup the rest of the architecture (IDT, etc) */ + Status = BlpArchInitialize(1); + if (!NT_SUCCESS(Status)) + { + /* Destroy memory manager in phase 1 */ + EarlyPrint(L"Arch2 init failed\n"); + //BlpMmDestroy(1); + return Status; + } + EarlyPrint(L"TODO!\n"); Status = STATUS_NOT_IMPLEMENTED;
Modified: trunk/reactos/boot/environ/lib/firmware/efi/firmware.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/firmware/e... ============================================================================== --- trunk/reactos/boot/environ/lib/firmware/efi/firmware.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/firmware/efi/firmware.c [iso-8859-1] Sun Sep 6 20:55:50 2015 @@ -207,6 +207,35 @@
/* Make the EFI call */ EfiStatus = EfiBS->FreePages(PhysicalAddress, Pages); + + /* Switch back to protected mode if we came from there */ + if (OldMode != BlRealMode) + { + BlpArchSwitchContext(OldMode); + } + + /* Convert the error to an NTSTATUS */ + return EfiGetNtStatusCode(EfiStatus); +} + +NTSTATUS +EfiStall ( + _In_ ULONG StallTime + ) +{ + BL_ARCH_MODE OldMode; + EFI_STATUS EfiStatus; + + /* Are we in protected mode? */ + OldMode = CurrentExecutionContext->Mode; + if (OldMode != BlRealMode) + { + /* FIXME: Not yet implemented */ + return STATUS_NOT_IMPLEMENTED; + } + + /* Make the EFI call */ + EfiStatus = EfiBS->Stall(StallTime);
/* Switch back to protected mode if we came from there */ if (OldMode != BlRealMode) @@ -749,7 +778,7 @@ { /* Set the initial key toggle state */ KeyToggleState = EFI_TOGGLE_STATE_VALID | 40; - EfiConInExSetState(EfiST->ConsoleInHandle, &KeyToggleState); + EfiConInExSetState(EfiConInEx, &KeyToggleState); }
/* Setup the watchdog timer */
Modified: trunk/reactos/boot/environ/lib/mm/heapalloc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/mm/heapall... ============================================================================== --- trunk/reactos/boot/environ/lib/mm/heapalloc.c [iso-8859-1] (original) +++ trunk/reactos/boot/environ/lib/mm/heapalloc.c [iso-8859-1] Sun Sep 6 20:55:50 2015 @@ -47,10 +47,10 @@ typedef struct _BL_HEAP_BOUNDARIES { LIST_ENTRY ListEntry; - ULONG_PTR HeapHigh; + ULONG_PTR HeapEnd; ULONG_PTR HeapLimit; - ULONG_PTR HeapBottom; - PBL_BUSY_HEAP_ENTRY HeapTop; + ULONG_PTR HeapBase; + PBL_BUSY_HEAP_ENTRY HeapStart; } BL_HEAP_BOUNDARIES, *PBL_HEAP_BOUNDARIES;
ULONG HapInitializationStatus; @@ -125,7 +125,7 @@
/* Check if we have a page free above the heap */ HeapLimit = Heap->HeapLimit + PAGE_SIZE; - if (HeapLimit <= Heap->HeapHigh) + if (HeapLimit <= Heap->HeapEnd) { EarlyPrint(L"Heap extension TODO\n"); return STATUS_INSUFFICIENT_RESOURCES; @@ -147,32 +147,32 @@
/* Set the heap bottom, limit, and top */ NewHeap = (PBL_HEAP_BOUNDARIES)HeapBase->Buffer; - NewHeap->HeapBottom = (ULONG_PTR)HeapBase; + NewHeap->HeapBase = (ULONG_PTR)HeapBase; NewHeap->HeapLimit = (ULONG_PTR)HeapBase + AlignedSize; - NewHeap->HeapTop = (PBL_BUSY_HEAP_ENTRY)(NewHeap + 1); + NewHeap->HeapStart = (PBL_BUSY_HEAP_ENTRY)(NewHeap + 1);
/* Set the buffer links */ HeapBase->BufferPrevious.P = NULL; - HeapBase->BufferNext.P = NewHeap->HeapTop; + HeapBase->BufferNext.P = NewHeap->HeapStart;
/* Set the buffer at the top of the heap and mark it as being free */ - NewHeap->HeapTop->BufferPrevious.P = HeapBase; - NewHeap->HeapTop->BufferNext.P = NewHeap->HeapTop; - NewHeap->HeapTop->BufferNext.BufferFree = 1; - NewHeap->HeapTop->BufferNext.BufferOnHeap = 1; + NewHeap->HeapStart->BufferPrevious.P = HeapBase; + NewHeap->HeapStart->BufferNext.P = NewHeap->HeapStart; + NewHeap->HeapStart->BufferNext.BufferFree = 1; + NewHeap->HeapStart->BufferNext.BufferOnHeap = 1;
/* Is this the first heap ever? */ if (IsListEmpty(&MmHeapBoundaries)) { /* We will host the free list at the top of the heap */ - MmFreeList = (PBL_FREE_HEAP_ENTRY*)((ULONG_PTR)NewHeap->HeapLimit - sizeof(BL_HEAP_BOUNDARIES)); + MmFreeList = (PBL_FREE_HEAP_ENTRY*)((ULONG_PTR)NewHeap->HeapLimit - 8 * sizeof(PBL_FREE_HEAP_ENTRY)); NewHeap->HeapLimit = (ULONG_PTR)MmFreeList; RtlZeroMemory(MmFreeList, 8 * sizeof(PBL_FREE_HEAP_ENTRY)); }
/* Remove a page on top */ HeapLimit = NewHeap->HeapLimit; - NewHeap->HeapHigh = NewHeap->HeapLimit; + NewHeap->HeapEnd = NewHeap->HeapLimit; NewHeap->HeapLimit -= PAGE_SIZE;
/* Add us into the heap list */ @@ -595,29 +595,24 @@ ListEntry);
/* Check if we have space in the heap page for this allocation? */ - FreeEntry = Heap->HeapTop; + FreeEntry = Heap->HeapStart; NextEntry = (PBL_BUSY_HEAP_ENTRY)((ULONG_PTR)FreeEntry + BufferSize); - - EarlyPrint(L"Free Entry: %p Size: %lx Next: %p\n", FreeEntry, BufferSize, NextEntry); - - EarlyPrint(L"Heap Limit: %p\n", Heap->HeapLimit); - EarlyPrint(L"Minus one busy entry: %p\n", Heap->HeapLimit - sizeof(BL_BUSY_HEAP_ENTRY));
if ((NextEntry >= FreeEntry) && ((ULONG_PTR)NextEntry <= Heap->HeapLimit - sizeof(BL_BUSY_HEAP_ENTRY))) { /* Update the heap top pointer past this allocation */ - Heap->HeapTop = NextEntry; + Heap->HeapStart = NextEntry;
/* Make this allocation point to the slot */ - FreeEntry->BufferNext.P = Heap->HeapTop; + FreeEntry->BufferNext.P = Heap->HeapStart;
/* And make the free heap entry point back to us */ - Heap->HeapTop->BufferNext.P = FreeEntry; + Heap->HeapStart->BufferNext.P = FreeEntry;
/* Mark the heap entry as being free and on the heap */ - Heap->HeapTop->BufferNext.BufferFree = 1; - Heap->HeapTop->BufferNext.BufferOnHeap = 1; + Heap->HeapStart->BufferNext.BufferFree = 1; + Heap->HeapStart->BufferNext.BufferOnHeap = 1;
/* The previously freed entry on the heap page is now ours */ BusyEntry = FreeEntry; @@ -639,6 +634,7 @@ BusyEntry->BufferNext.P = MmHapDecodeLink(BusyEntry->BufferNext);
/* Return the entry's data buffer */ + EarlyPrint(L"Returning buffer at 0x%p\n", &BusyEntry->Buffer); return &BusyEntry->Buffer; }
@@ -668,8 +664,8 @@ Heap = CONTAINING_RECORD(NextEntry, BL_HEAP_BOUNDARIES, ListEntry);
/* Is this entry part of this heap? */ - if (((ULONG_PTR)Heap->HeapBottom <= (ULONG_PTR)BusyEntry) && - ((ULONG_PTR)BusyEntry < (ULONG_PTR)Heap->HeapTop)) + if (((ULONG_PTR)Heap->HeapBase <= (ULONG_PTR)BusyEntry) && + ((ULONG_PTR)BusyEntry < (ULONG_PTR)Heap->HeapStart)) { /* Ignore double-free */ if (BusyEntry->BufferNext.BufferFree)
Added: trunk/reactos/boot/environ/lib/platform/time.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/environ/lib/platform/t... ============================================================================== --- trunk/reactos/boot/environ/lib/platform/time.c (added) +++ trunk/reactos/boot/environ/lib/platform/time.c [iso-8859-1] Sun Sep 6 20:55:50 2015 @@ -0,0 +1,88 @@ +/* + * COPYRIGHT: See COPYING.ARM in the top level directory + * PROJECT: ReactOS UEFI Boot Library + * FILE: boot/environ/lib/platform/time.c + * PURPOSE: Boot Library Time Management Routines + * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include "bl.h" + +/* DATA VARIABLES ************************************************************/ + +ULONGLONG BlpTimePerformanceFrequency; + +NTSTATUS +BlpTimeMeasureTscFrequency ( + VOID + ) +{ + ULONG Count; + INT CpuInfo[4]; + ULONGLONG TimeStamp1, TimeStamp2, Delta; + + /* Check if the ISVM bit it set, meaning we're in a hypervisor */ + __cpuid(CpuInfo, 1); + Count = CpuInfo[2] & 0x80000000 ? 10 : 1; + + /* Loop trying to get an accurate TSC */ + do + { + /* Stall for 1us and get count 1 */ + EfiStall(1); + TimeStamp1 = __rdtsc(); + + /* Stall for 1000us and get count 2*/ + EfiStall(1000); + TimeStamp2 = __rdtsc(); + + /* Stall for 9000us and get the difference */ + EfiStall(9000); + Delta = __rdtsc() - TimeStamp2; + + /* Keep going as long as the TSC is fluctuating */ + --Count; + } while (((TimeStamp2 - TimeStamp1) > Delta) && (Count)); + + /* Set the frequency based on the two measurements we took */ + BlpTimePerformanceFrequency = 125 * (Delta - (TimeStamp2 - TimeStamp1)) & 0x1FFFFFFFFFFFFFF; + EarlyPrint(L"Computed frequency as: %I64d\n", BlpTimePerformanceFrequency); + return STATUS_SUCCESS; +} + +NTSTATUS +BlpTimeCalibratePerformanceCounter ( + VOID + ) +{ + INT CpuInfo[4]; + + /* Check if the ISVM bit it set, meaning we're in a hypervisor */ + __cpuid(CpuInfo, 1); + if (CpuInfo[2] & 0x80000000) + { + /* Get the Hypervisor Identification Leaf */ + __cpuid(CpuInfo, 0x40000001); + + /* Is this Hyper-V? */ + if (CpuInfo[0] == '1#vH') + { + /* Get the Hypervisor Feature Identification Leaf */ + __cpuid(CpuInfo, 0x40000003); + + /* Check if HV_X64_MSR_REFERENCE_TSC is present */ + if (CpuInfo[3] & 0x100) + { + /* Read the TSC frequency from the MSR */ + BlpTimePerformanceFrequency = __readmsr(0x40000022); + EarlyPrint(L"Using frequency as: %I64d\n", BlpTimePerformanceFrequency); + return STATUS_SUCCESS; + } + } + } + + /* On other systems, compute it */ + return BlpTimeMeasureTscFrequency(); +}
Propchange: trunk/reactos/boot/environ/lib/platform/time.c ------------------------------------------------------------------------------ svn:eol-style = native