[BOOTLIB]: Rough sketches of BlImgLoadBootApplication, BlImgStartBootApplication...
[reactos.git] / reactos / boot / environ / lib / platform / time.c
1 /*
2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Library
4 * FILE: boot/environ/lib/platform/time.c
5 * PURPOSE: Boot Library Time Management Routines
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "bl.h"
12
13 /* DATA VARIABLES ************************************************************/
14
15 ULONGLONG BlpTimePerformanceFrequency;
16
17 /* FUNCTIONS *****************************************************************/
18
19 NTSTATUS
20 BlpTimeMeasureTscFrequency (
21 VOID
22 )
23 {
24 ULONG Count;
25 INT CpuInfo[4];
26 ULONGLONG TimeStamp1, TimeStamp2, Delta;
27
28 /* Check if the ISVM bit it set, meaning we're in a hypervisor */
29 __cpuid(CpuInfo, 1);
30 Count = CpuInfo[2] & 0x80000000 ? 10 : 1;
31
32 /* Loop trying to get an accurate TSC */
33 do
34 {
35 /* Stall for 1us and get count 1 */
36 EfiStall(1);
37 TimeStamp1 = __rdtsc();
38
39 /* Stall for 1000us and get count 2*/
40 EfiStall(1000);
41 TimeStamp2 = __rdtsc();
42
43 /* Stall for 9000us and get the difference */
44 EfiStall(9000);
45 Delta = __rdtsc() - TimeStamp2;
46
47 /* Keep going as long as the TSC is fluctuating */
48 --Count;
49 } while (((TimeStamp2 - TimeStamp1) > Delta) && (Count));
50
51 /* Set the frequency based on the two measurements we took */
52 BlpTimePerformanceFrequency = 125 * (Delta - (TimeStamp2 - TimeStamp1)) & 0x1FFFFFFFFFFFFFF;
53 return STATUS_SUCCESS;
54 }
55
56 NTSTATUS
57 BlpTimeCalibratePerformanceCounter (
58 VOID
59 )
60 {
61 INT CpuInfo[4];
62
63 /* Check if the ISVM bit it set, meaning we're in a hypervisor */
64 __cpuid(CpuInfo, 1);
65 if (CpuInfo[2] & 0x80000000)
66 {
67 /* Get the Hypervisor Identification Leaf */
68 __cpuid(CpuInfo, 0x40000001);
69
70 /* Is this Hyper-V? */
71 if (CpuInfo[0] == '1#vH')
72 {
73 /* Get the Hypervisor Feature Identification Leaf */
74 __cpuid(CpuInfo, 0x40000003);
75
76 /* Check if HV_X64_MSR_REFERENCE_TSC is present */
77 if (CpuInfo[3] & 0x100)
78 {
79 /* Read the TSC frequency from the MSR */
80 BlpTimePerformanceFrequency = __readmsr(0x40000022);
81 EfiPrintf(L"Using Hyper-V frequency as: %I64d\r\n", BlpTimePerformanceFrequency);
82 return STATUS_SUCCESS;
83 }
84 }
85 }
86
87 /* On other systems, compute it */
88 return BlpTimeMeasureTscFrequency();
89 }
90
91 ULONGLONG
92 BlTimeQueryPerformanceCounter (
93 _Out_opt_ PLARGE_INTEGER Frequency
94 )
95 {
96 /* Check if caller wants frequency */
97 if (Frequency)
98 {
99 /* Return it */
100 Frequency->QuadPart = BlpTimePerformanceFrequency;
101 }
102
103 /* Return the TSC value */
104 return __rdtsc();
105 };