[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)

svn path=/trunk/; revision=69071
This commit is contained in:
Alex Ionescu 2015-09-06 20:55:50 +00:00
parent d8b6cfc7f3
commit 3e997c870b
7 changed files with 221 additions and 33 deletions

View file

@ -17,7 +17,8 @@ list(APPEND BOOTLIB_SOURCE
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

View file

@ -522,6 +522,18 @@ EfiAllocatePages (
_Inout_ EFI_PHYSICAL_ADDRESS* Memory
);
NTSTATUS
EfiStall (
_In_ ULONG StallTime
);
/* PLATFORM TIMER ROUTINES ***************************************************/
NTSTATUS
BlpTimeCalibratePerformanceCounter (
VOID
);
/* UTILITY ROUTINES **********************************************************/
EFI_STATUS

View file

@ -19,13 +19,20 @@ PBL_ARCH_CONTEXT CurrentExecutionContext;
/* 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 @@ BlpArchInitialize (
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 @@ BlpArchInitialize (
__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
{

View file

@ -132,6 +132,50 @@ InitializeLibrary (
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;

View file

@ -218,6 +218,35 @@ EfiFreePages (
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)
{
BlpArchSwitchContext(OldMode);
}
/* Convert the error to an NTSTATUS */
return EfiGetNtStatusCode(EfiStatus);
}
NTSTATUS
EfiAllocatePages (
_In_ ULONG Type,
@ -749,7 +778,7 @@ BlpFwInitialize (
{
/* Set the initial key toggle state */
KeyToggleState = EFI_TOGGLE_STATE_VALID | 40;
EfiConInExSetState(EfiST->ConsoleInHandle, &KeyToggleState);
EfiConInExSetState(EfiConInEx, &KeyToggleState);
}
/* Setup the watchdog timer */

View file

@ -47,10 +47,10 @@ typedef struct _BL_BUSY_HEAP_ENTRY
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 @@ MmHapHeapAllocatorExtend (
/* 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 @@ MmHapHeapAllocatorExtend (
/* 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 @@ BlMmAllocateHeap (
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 @@ BlMmAllocateHeap (
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 @@ BlMmFreeHeap (
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)

View file

@ -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();
}