Implement detection of timer capabilities
This commit is contained in:
@@ -140,6 +140,18 @@ typedef enum _CPU_VENDOR
|
||||
CPU_VENDOR_UNKNOWN = 0xFFFFFFFF
|
||||
} CPU_VENDOR, *PCPU_VENDOR;
|
||||
|
||||
/* CPUID advanced power management features (0x80000007) enumeration list */
|
||||
typedef enum _CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT
|
||||
{
|
||||
CPUID_FEATURES_EDX_TS = 1 << 0, /* Temperature Sensor */
|
||||
CPUID_FEATURES_EDX_FIS = 1 << 1, /* Frequency ID Selection */
|
||||
CPUID_FEATURES_EDX_VIS = 1 << 2, /* Voltage ID Selection */
|
||||
CPUID_FEATURES_EDX_TTS = 1 << 3, /* ThermaTrip Support */
|
||||
CPUID_FEATURES_EDX_HTC = 1 << 4, /* Hardware Thermal Throttling */
|
||||
CPUID_FEATURES_EDX_STC = 1 << 5, /* Software Thermal Throttling */
|
||||
CPUID_FEATURES_EDX_TSCI = 1 << 8 /* TSC Invariant */
|
||||
} CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT, *PCPUID_FEATURES_ADVANCED_POWER_MANAGEMENT;
|
||||
|
||||
/* CPUID extended features (0x80000001) enumeration list */
|
||||
typedef enum _CPUID_FEATURES_EXTENDED
|
||||
{
|
||||
@@ -181,6 +193,23 @@ typedef enum _CPUID_FEATURES_EXTENDED
|
||||
CPUID_FEATURES_EDX_3DNOW = 1 << 31
|
||||
} CPUID_FEATURES_EXTENDED, *PCPUID_FEATURES_EXTENDED;
|
||||
|
||||
/* CPUID Thermal and Power Management features (0x00000006) enumeration list */
|
||||
typedef enum _CPUID_FEATURES_POWER_MANAGEMENT
|
||||
{
|
||||
CPUID_FEATURES_EAX_DTHERM = 1 << 0,
|
||||
CPUID_FEATURES_EAX_IDA = 1 << 1,
|
||||
CPUID_FEATURES_EAX_ARAT = 1 << 2,
|
||||
CPUID_FEATURES_EAX_PLN = 1 << 4,
|
||||
CPUID_FEATURES_EAX_PTS = 1 << 6,
|
||||
CPUID_FEATURES_EAX_HWP = 1 << 7,
|
||||
CPUID_FEATURES_EAX_HWP_NOTIFY = 1 << 8,
|
||||
CPUID_FEATURES_EAX_HWP_ACT_WINDOW = 1 << 9,
|
||||
CPUID_FEATURES_EAX_HWP_EPP = 1 << 10,
|
||||
CPUID_FEATURES_EAX_HWP_PKG_REQ = 1 << 11,
|
||||
CPUID_FEATURES_EAX_HWP_HIGHEST_PERF_CHANGE = 1 << 15,
|
||||
CPUID_FEATURES_EAX_HFI = 1 << 19
|
||||
} CPUID_FEATURES_LEAF6, *PCPUID_FEATURES_LEAF6;
|
||||
|
||||
/* CPUID STD1 features (0x00000001) enumeration list */
|
||||
typedef enum _CPUID_FEATURES_STANDARD1
|
||||
{
|
||||
@@ -207,7 +236,7 @@ typedef enum _CPUID_FEATURES_STANDARD1
|
||||
CPUID_FEATURES_ECX_X2APIC = 1 << 21,
|
||||
CPUID_FEATURES_ECX_MOVBE = 1 << 22,
|
||||
CPUID_FEATURES_ECX_POPCNT = 1 << 23,
|
||||
CPUID_FEATURES_ECX_TSC = 1 << 24,
|
||||
CPUID_FEATURES_ECX_TSC_DEADLINE = 1 << 24,
|
||||
CPUID_FEATURES_ECX_AES = 1 << 25,
|
||||
CPUID_FEATURES_ECX_XSAVE = 1 << 26,
|
||||
CPUID_FEATURES_ECX_OSXSAVE = 1 << 27,
|
||||
@@ -381,14 +410,18 @@ typedef enum _CPUID_FEATURES_STANDARD7_LEAF1
|
||||
/* CPUID requests */
|
||||
typedef enum _CPUID_REQUESTS
|
||||
{
|
||||
CPUID_GET_VENDOR_STRING,
|
||||
CPUID_GET_STANDARD1_FEATURES,
|
||||
CPUID_GET_TLB_CACHE,
|
||||
CPUID_GET_SERIAL,
|
||||
CPUID_GET_CACHE_TOPOLOGY,
|
||||
CPUID_GET_MONITOR_MWAIT,
|
||||
CPUID_GET_POWER_MANAGEMENT,
|
||||
CPUID_GET_STANDARD7_FEATURES
|
||||
CPUID_GET_VENDOR_STRING = 0x00000000,
|
||||
CPUID_GET_STANDARD1_FEATURES = 0x00000001,
|
||||
CPUID_GET_TLB_CACHE = 0x00000002,
|
||||
CPUID_GET_SERIAL = 0x00000003,
|
||||
CPUID_GET_CACHE_TOPOLOGY = 0x00000004,
|
||||
CPUID_GET_MONITOR_MWAIT = 0x00000005,
|
||||
CPUID_GET_POWER_MANAGEMENT = 0x00000006,
|
||||
CPUID_GET_STANDARD7_FEATURES = 0x00000007,
|
||||
CPUID_GET_TSC_CRYSTAL_CLOCK = 0x00000015,
|
||||
CPUID_GET_EXTENDED_MAX = 0x80000000,
|
||||
CPUID_GET_EXTENDED_FEATURES = 0x80000001,
|
||||
CPUID_GET_ADVANCED_POWER_MANAGEMENT = 0x80000007
|
||||
} CPUID_REQUESTS, *PCPUID_REQUESTS;
|
||||
|
||||
/* Interrupt handler */
|
||||
|
||||
@@ -339,5 +339,17 @@ typedef union _PIC_I8259_ICW4
|
||||
UCHAR Bits;
|
||||
} PIC_I8259_ICW4, *PPIC_I8259_ICW4;
|
||||
|
||||
typedef struct _TIMER_CAPABILITIES
|
||||
{
|
||||
BOOLEAN Arat;
|
||||
BOOLEAN Art;
|
||||
BOOLEAN InvariantTsc;
|
||||
BOOLEAN RDTSCP;
|
||||
ULONG TimerFrequency;
|
||||
BOOLEAN TscDeadline;
|
||||
ULONG TscDenominator;
|
||||
ULONG TscNumerator;
|
||||
} TIMER_CAPABILITIES, *PTIMER_CAPABILITIES;
|
||||
|
||||
#endif /* __XTOS_ASSEMBLER__ */
|
||||
#endif /* __XTDK_AMD64_HLTYPES_H */
|
||||
|
||||
@@ -22,7 +22,9 @@ typedef enum _APIC_MODE APIC_MODE, *PAPIC_MODE;
|
||||
typedef enum _APIC_REGISTER APIC_REGISTER, *PAPIC_REGISTER;
|
||||
typedef enum _APIC_TIMER_DIVISOR APIC_TIMER_DIVISOR, *PAPIC_TIMER_DIVISOR;
|
||||
typedef enum _CPU_VENDOR CPU_VENDOR, *PCPU_VENDOR;
|
||||
typedef enum _CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT, *PCPUID_FEATURES_ADVANCED_POWER_MANAGEMENT;
|
||||
typedef enum _CPUID_FEATURES_EXTENDED CPUID_FEATURES_EXTENDED, *PCPUID_FEATURES_EXTENDED;
|
||||
typedef enum _CPUID_FEATURES_POWER_MANAGEMENT CPUID_FEATURES_POWER_MANAGEMENT, *PCPUID_FEATURES_POWER_MANAGEMENT;
|
||||
typedef enum _CPUID_FEATURES_STANDARD1 CPUID_FEATURES_STANDARD1, *PCPUID_FEATURES_STANDARD1;
|
||||
typedef enum _CPUID_FEATURES_STANDARD7_LEAF0 CPUID_FEATURES_STANDARD7_LEAF0, *PCPUID_FEATURES_STANDARD7_LEAF0;
|
||||
typedef enum _CPUID_FEATURES_STANDARD7_LEAF1 CPUID_FEATURES_STANDARD7_LEAF1, *PCPUID_FEATURES_STANDARD7_LEAF1;
|
||||
@@ -67,6 +69,7 @@ typedef struct _MMPTE_SUBSECTION MMPTE_SUBSECTION, *PMMPTE_SUBSECTION;
|
||||
typedef struct _MMPTE_TRANSITION MMPTE_TRANSITION, *PMMPTE_TRANSITION;
|
||||
typedef struct _POOL_DESCRIPTOR POOL_DESCRIPTOR, *PPOOL_DESCRIPTOR;
|
||||
typedef struct _THREAD_ENVIRONMENT_BLOCK THREAD_ENVIRONMENT_BLOCK, *PTHREAD_ENVIRONMENT_BLOCK;
|
||||
typedef struct _TIMER_CAPABILITIES TIMER_CAPABILITIES, *PTIMER_CAPABILITIES;
|
||||
|
||||
/* Unions forward references */
|
||||
typedef union _APIC_BASE_REGISTER APIC_BASE_REGISTER, *PAPIC_BASE_REGISTER;
|
||||
|
||||
@@ -105,6 +105,18 @@ typedef enum _CPU_VENDOR
|
||||
CPU_VENDOR_UNKNOWN = 0xFFFFFFFF
|
||||
} CPU_VENDOR, *PCPU_VENDOR;
|
||||
|
||||
/* CPUID advanced power management features (0x80000007) enumeration list */
|
||||
typedef enum _CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT
|
||||
{
|
||||
CPUID_FEATURES_EDX_TS = 1 << 0, /* Temperature Sensor */
|
||||
CPUID_FEATURES_EDX_FIS = 1 << 1, /* Frequency ID Selection */
|
||||
CPUID_FEATURES_EDX_VIS = 1 << 2, /* Voltage ID Selection */
|
||||
CPUID_FEATURES_EDX_TTS = 1 << 3, /* ThermaTrip Support */
|
||||
CPUID_FEATURES_EDX_HTC = 1 << 4, /* Hardware Thermal Throttling */
|
||||
CPUID_FEATURES_EDX_STC = 1 << 5, /* Software Thermal Throttling */
|
||||
CPUID_FEATURES_EDX_TSCI = 1 << 8 /* TSC Invariant */
|
||||
} CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT, *PCPUID_FEATURES_ADVANCED_POWER_MANAGEMENT;
|
||||
|
||||
/* CPUID extended features (0x80000001) enumeration list */
|
||||
typedef enum _CPUID_FEATURES_EXTENDED
|
||||
{
|
||||
@@ -146,6 +158,23 @@ typedef enum _CPUID_FEATURES_EXTENDED
|
||||
CPUID_FEATURES_EDX_3DNOW = 1 << 31
|
||||
} CPUID_FEATURES_EXTENDED, *PCPUID_FEATURES_EXTENDED;
|
||||
|
||||
/* CPUID Thermal and Power Management features (0x00000006) enumeration list */
|
||||
typedef enum _CPUID_FEATURES_POWER_MANAGEMENT
|
||||
{
|
||||
CPUID_FEATURES_EAX_DTHERM = 1 << 0,
|
||||
CPUID_FEATURES_EAX_IDA = 1 << 1,
|
||||
CPUID_FEATURES_EAX_ARAT = 1 << 2,
|
||||
CPUID_FEATURES_EAX_PLN = 1 << 4,
|
||||
CPUID_FEATURES_EAX_PTS = 1 << 6,
|
||||
CPUID_FEATURES_EAX_HWP = 1 << 7,
|
||||
CPUID_FEATURES_EAX_HWP_NOTIFY = 1 << 8,
|
||||
CPUID_FEATURES_EAX_HWP_ACT_WINDOW = 1 << 9,
|
||||
CPUID_FEATURES_EAX_HWP_EPP = 1 << 10,
|
||||
CPUID_FEATURES_EAX_HWP_PKG_REQ = 1 << 11,
|
||||
CPUID_FEATURES_EAX_HWP_HIGHEST_PERF_CHANGE = 1 << 15,
|
||||
CPUID_FEATURES_EAX_HFI = 1 << 19
|
||||
} CPUID_FEATURES_LEAF6, *PCPUID_FEATURES_LEAF6;
|
||||
|
||||
/* CPUID STD1 features (0x00000001) enumeration list */
|
||||
typedef enum _CPUID_FEATURES_STANDARD1
|
||||
{
|
||||
@@ -172,7 +201,7 @@ typedef enum _CPUID_FEATURES_STANDARD1
|
||||
CPUID_FEATURES_ECX_X2APIC = 1 << 21,
|
||||
CPUID_FEATURES_ECX_MOVBE = 1 << 22,
|
||||
CPUID_FEATURES_ECX_POPCNT = 1 << 23,
|
||||
CPUID_FEATURES_ECX_TSC = 1 << 24,
|
||||
CPUID_FEATURES_ECX_TSC_DEADLINE = 1 << 24,
|
||||
CPUID_FEATURES_ECX_AES = 1 << 25,
|
||||
CPUID_FEATURES_ECX_XSAVE = 1 << 26,
|
||||
CPUID_FEATURES_ECX_OSXSAVE = 1 << 27,
|
||||
@@ -346,14 +375,18 @@ typedef enum _CPUID_FEATURES_STANDARD7_LEAF1
|
||||
/* CPUID requests */
|
||||
typedef enum _CPUID_REQUESTS
|
||||
{
|
||||
CPUID_GET_VENDOR_STRING,
|
||||
CPUID_GET_STANDARD1_FEATURES,
|
||||
CPUID_GET_TLB_CACHE,
|
||||
CPUID_GET_SERIAL,
|
||||
CPUID_GET_CACHE_TOPOLOGY,
|
||||
CPUID_GET_MONITOR_MWAIT,
|
||||
CPUID_GET_POWER_MANAGEMENT,
|
||||
CPUID_GET_STANDARD7_FEATURES
|
||||
CPUID_GET_VENDOR_STRING = 0x00000000,
|
||||
CPUID_GET_STANDARD1_FEATURES = 0x00000001,
|
||||
CPUID_GET_TLB_CACHE = 0x00000002,
|
||||
CPUID_GET_SERIAL = 0x00000003,
|
||||
CPUID_GET_CACHE_TOPOLOGY = 0x00000004,
|
||||
CPUID_GET_MONITOR_MWAIT = 0x00000005,
|
||||
CPUID_GET_POWER_MANAGEMENT = 0x00000006,
|
||||
CPUID_GET_STANDARD7_FEATURES = 0x00000007,
|
||||
CPUID_GET_TSC_CRYSTAL_CLOCK = 0x00000015,
|
||||
CPUID_GET_EXTENDED_MAX = 0x80000000,
|
||||
CPUID_GET_EXTENDED_FEATURES = 0x80000001,
|
||||
CPUID_GET_ADVANCED_POWER_MANAGEMENT = 0x80000007
|
||||
} CPUID_REQUESTS, *PCPUID_REQUESTS;
|
||||
|
||||
/* Interrupt handler */
|
||||
|
||||
@@ -346,5 +346,18 @@ typedef union _PIC_I8259_ICW4
|
||||
UCHAR Bits;
|
||||
} PIC_I8259_ICW4, *PPIC_I8259_ICW4;
|
||||
|
||||
/* Timer Capabilities */
|
||||
typedef struct _TIMER_CAPABILITIES
|
||||
{
|
||||
BOOLEAN Arat;
|
||||
BOOLEAN Art;
|
||||
BOOLEAN InvariantTsc;
|
||||
BOOLEAN RDTSCP;
|
||||
ULONG TimerFrequency;
|
||||
BOOLEAN TscDeadline;
|
||||
ULONG TscDenominator;
|
||||
ULONG TscNumerator;
|
||||
} TIMER_CAPABILITIES, *PTIMER_CAPABILITIES;
|
||||
|
||||
#endif /* __XTOS_ASSEMBLER__ */
|
||||
#endif /* __XTDK_I686_HLTYPES_H */
|
||||
|
||||
@@ -22,7 +22,9 @@ typedef enum _APIC_MODE APIC_MODE, *PAPIC_MODE;
|
||||
typedef enum _APIC_REGISTER APIC_REGISTER, *PAPIC_REGISTER;
|
||||
typedef enum _APIC_TIMER_DIVISOR APIC_TIMER_DIVISOR, *PAPIC_TIMER_DIVISOR;
|
||||
typedef enum _CPU_VENDOR CPU_VENDOR, *PCPU_VENDOR;
|
||||
typedef enum _CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT CPUID_FEATURES_ADVANCED_POWER_MANAGEMENT, *PCPUID_FEATURES_ADVANCED_POWER_MANAGEMENT;
|
||||
typedef enum _CPUID_FEATURES_EXTENDED CPUID_FEATURES_EXTENDED, *PCPUID_FEATURES_EXTENDED;
|
||||
typedef enum _CPUID_FEATURES_POWER_MANAGEMENT CPUID_FEATURES_POWER_MANAGEMENT, *PCPUID_FEATURES_POWER_MANAGEMENT;
|
||||
typedef enum _CPUID_FEATURES_STANDARD1 CPUID_FEATURES_STANDARD1, *PCPUID_FEATURES_STANDARD1;
|
||||
typedef enum _CPUID_FEATURES_STANDARD7_LEAF0 CPUID_FEATURES_STANDARD7_LEAF0, *PCPUID_FEATURES_STANDARD7_LEAF0;
|
||||
typedef enum _CPUID_FEATURES_STANDARD7_LEAF1 CPUID_FEATURES_STANDARD7_LEAF1, *PCPUID_FEATURES_STANDARD7_LEAF1;
|
||||
@@ -76,6 +78,7 @@ typedef struct _MMPML3_PTE_SUBSECTION MMPML3_PTE_SUBSECTION, *PMMPML3_PTE_SUBSEC
|
||||
typedef struct _MMPML3_PTE_TRANSITION MMPML3_PTE_TRANSITION, *PMMPML3_PTE_TRANSITION;
|
||||
typedef struct _POOL_DESCRIPTOR POOL_DESCRIPTOR, *PPOOL_DESCRIPTOR;
|
||||
typedef struct _THREAD_ENVIRONMENT_BLOCK THREAD_ENVIRONMENT_BLOCK, *PTHREAD_ENVIRONMENT_BLOCK;
|
||||
typedef struct _TIMER_CAPABILITIES TIMER_CAPABILITIES, *PTIMER_CAPABILITIES;
|
||||
|
||||
/* Unions forward references */
|
||||
typedef union _APIC_BASE_REGISTER APIC_BASE_REGISTER, *PAPIC_BASE_REGISTER;
|
||||
|
||||
@@ -42,5 +42,8 @@ APIC_MODE HL::Pic::ApicMode;
|
||||
/* Kernel profiling interval */
|
||||
ULONG HL::Timer::ProfilingInterval;
|
||||
|
||||
/* Timer capabilities */
|
||||
TIMER_CAPABILITIES HL::Timer::TimerCapabilities = {0};
|
||||
|
||||
/* APIC timer frequency */
|
||||
ULONG HL::Timer::TimerFrequency;
|
||||
|
||||
@@ -45,6 +45,6 @@ HL::Cpu::InitializeProcessor(VOID)
|
||||
/* Set the APIC running level */
|
||||
HL::RunLevel::SetRunLevel(KE::Processor::GetCurrentProcessorBlock()->RunLevel);
|
||||
|
||||
/* Initialize APIC timer */
|
||||
HL::Timer::InitializeApicTimer();
|
||||
/* Initialize timer */
|
||||
HL::Timer::InitializeTimer();
|
||||
}
|
||||
|
||||
@@ -21,11 +21,14 @@ XTSTATUS
|
||||
HL::Timer::CalibrateApicTimer()
|
||||
{
|
||||
ULONG CurrentCount, Frequency, InitialCount;
|
||||
XTSTATUS Status;
|
||||
|
||||
/* Get APIC timer frequency from the Core Crystal Clock */
|
||||
Status = GetApicTimerFrequency(&Frequency);
|
||||
if(Status != STATUS_SUCCESS || !Frequency)
|
||||
if(TimerCapabilities.Art && TimerCapabilities.TimerFrequency != 0)
|
||||
{
|
||||
/* CCC available, use it as the source of APIC timer frequency */
|
||||
Frequency = TimerCapabilities.TimerFrequency;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* CCC unavailable, fallback to PIT calibration */
|
||||
InitialCount = 0xFFFFFFFF;
|
||||
@@ -59,76 +62,6 @@ HL::Timer::CalibrateApicTimer()
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the APIC timer frequency from the Core Crystal Clock.
|
||||
*
|
||||
* @param Frequency
|
||||
* Supplies a pointer to a variable that will receive the nominal APIC timer frequency in Hz.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
XTSTATUS
|
||||
HL::Timer::GetApicTimerFrequency(OUT PULONG Frequency)
|
||||
{
|
||||
CPUID_REGISTERS CpuRegisters;
|
||||
|
||||
/* Verify input parameter */
|
||||
if(!Frequency)
|
||||
{
|
||||
/* Invalid parameter passed */
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Initialize output parameter to 0 */
|
||||
*Frequency = 0;
|
||||
|
||||
/* Get maximum supported standard CPUID leaf */
|
||||
CpuRegisters.Leaf = 0;
|
||||
CpuRegisters.SubLeaf = 0;
|
||||
CpuRegisters.Eax = 0;
|
||||
CpuRegisters.Ebx = 0;
|
||||
CpuRegisters.Ecx = 0;
|
||||
CpuRegisters.Edx = 0;
|
||||
AR::CpuFunc::CpuId(&CpuRegisters);
|
||||
|
||||
/* Check if leaf 0x15 is supported by the CPU */
|
||||
if(CpuRegisters.Eax < 0x15)
|
||||
{
|
||||
/* Processor is too old, return error */
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Query Time Stamp Counter and Core Crystal Clock information */
|
||||
CpuRegisters.Leaf = 0x15;
|
||||
CpuRegisters.SubLeaf = 0;
|
||||
CpuRegisters.Eax = 0;
|
||||
CpuRegisters.Ebx = 0;
|
||||
CpuRegisters.Ecx = 0;
|
||||
CpuRegisters.Edx = 0;
|
||||
AR::CpuFunc::CpuId(&CpuRegisters);
|
||||
|
||||
/* Check if the leaf is properly enumerated */
|
||||
if(CpuRegisters.Eax == 0 || CpuRegisters.Ebx == 0)
|
||||
{
|
||||
/* Intel SDM: EAX or EBX is 0, the leaf is not properly enumerated, return error */
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Check if ECX contains the nominal frequency of the core crystal clock */
|
||||
if(CpuRegisters.Ecx == 0)
|
||||
{
|
||||
/* Hardware did not provide the exact frequency, return error */
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* Save the base frequency for the APIC Timer and return success */
|
||||
*Frequency = CpuRegisters.Ecx;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes and calibrates the Local APIC Timer.
|
||||
*
|
||||
@@ -160,6 +93,24 @@ HL::Timer::InitializeApicTimer(VOID)
|
||||
StopProfileInterrupt(ProfileXtKernel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a basic Timer initialization.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
HL::Timer::InitializeTimer(VOID)
|
||||
{
|
||||
/* Query timer capabilities */
|
||||
QueryTimerCapabilities();
|
||||
|
||||
/* Initialize the APIC timer */
|
||||
InitializeApicTimer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stalls the CPU execution for a specified duration (maximum 3 seconds) using the legacy PIT timer.
|
||||
*
|
||||
@@ -221,6 +172,147 @@ HL::Timer::PitStallExecution(IN ULONG MicroSeconds)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Probes the processor via CPUID to detect available modern timing and clock generation features.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTAPI
|
||||
VOID
|
||||
HL::Timer::QueryTimerCapabilities(VOID)
|
||||
{
|
||||
CPUID_REGISTERS CpuRegisters;
|
||||
ULONG MaxStandardLeaf;
|
||||
ULONG MaxExtendedLeaf;
|
||||
|
||||
/* Query maximum standard CPUID leaf */
|
||||
CpuRegisters.Leaf = CPUID_GET_VENDOR_STRING;
|
||||
CpuRegisters.SubLeaf = 0;
|
||||
CpuRegisters.Eax = 0;
|
||||
CpuRegisters.Ebx = 0;
|
||||
CpuRegisters.Ecx = 0;
|
||||
CpuRegisters.Edx = 0;
|
||||
AR::CpuFunc::CpuId(&CpuRegisters);
|
||||
|
||||
/* Save maximum supported standard CPUID leaf */
|
||||
MaxStandardLeaf = CpuRegisters.Eax;
|
||||
|
||||
/* Query maximum extended CPUID leaf */
|
||||
CpuRegisters.Leaf = CPUID_GET_EXTENDED_MAX;
|
||||
CpuRegisters.SubLeaf = 0;
|
||||
CpuRegisters.Eax = 0;
|
||||
CpuRegisters.Ebx = 0;
|
||||
CpuRegisters.Ecx = 0;
|
||||
CpuRegisters.Edx = 0;
|
||||
AR::CpuFunc::CpuId(&CpuRegisters);
|
||||
|
||||
/* Save maximum supported extended CPUID leaf */
|
||||
MaxExtendedLeaf = CpuRegisters.Eax;
|
||||
|
||||
/* Check TSC-Deadline mode if leaf supported */
|
||||
if(MaxStandardLeaf >= CPUID_GET_STANDARD1_FEATURES)
|
||||
{
|
||||
CpuRegisters.Leaf = CPUID_GET_STANDARD1_FEATURES;
|
||||
CpuRegisters.SubLeaf = 0;
|
||||
CpuRegisters.Eax = 0;
|
||||
CpuRegisters.Ebx = 0;
|
||||
CpuRegisters.Ecx = 0;
|
||||
CpuRegisters.Edx = 0;
|
||||
AR::CpuFunc::CpuId(&CpuRegisters);
|
||||
|
||||
/* Verify TSC-Deadline support */
|
||||
if(CpuRegisters.Ecx & CPUID_FEATURES_ECX_TSC_DEADLINE)
|
||||
{
|
||||
TimerCapabilities.TscDeadline = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check Always Running APIC Timer - ARAT if leaf supported */
|
||||
if(MaxStandardLeaf >= CPUID_GET_POWER_MANAGEMENT)
|
||||
{
|
||||
CpuRegisters.Leaf = CPUID_GET_POWER_MANAGEMENT;
|
||||
CpuRegisters.SubLeaf = 0;
|
||||
CpuRegisters.Eax = 0;
|
||||
CpuRegisters.Ebx = 0;
|
||||
CpuRegisters.Ecx = 0;
|
||||
CpuRegisters.Edx = 0;
|
||||
AR::CpuFunc::CpuId(&CpuRegisters);
|
||||
|
||||
/* Verify ARAT support */
|
||||
if(CpuRegisters.Eax & CPUID_FEATURES_EAX_ARAT)
|
||||
{
|
||||
TimerCapabilities.Arat = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check Always Running Timer - ART if leaf supported */
|
||||
if(MaxStandardLeaf >= CPUID_GET_TSC_CRYSTAL_CLOCK)
|
||||
{
|
||||
CpuRegisters.Leaf = CPUID_GET_TSC_CRYSTAL_CLOCK;
|
||||
CpuRegisters.SubLeaf = 0;
|
||||
CpuRegisters.Eax = 0;
|
||||
CpuRegisters.Ebx = 0;
|
||||
CpuRegisters.Ecx = 0;
|
||||
CpuRegisters.Edx = 0;
|
||||
AR::CpuFunc::CpuId(&CpuRegisters);
|
||||
|
||||
/* Verify ART support */
|
||||
if(CpuRegisters.Eax != 0 && CpuRegisters.Ebx != 0)
|
||||
{
|
||||
TimerCapabilities.Art = TRUE;
|
||||
|
||||
/* Save the TSC scaling ratios */
|
||||
TimerCapabilities.TscDenominator = CpuRegisters.Eax;
|
||||
TimerCapabilities.TscNumerator = CpuRegisters.Ebx;
|
||||
|
||||
/* Check if ECX contains the nominal frequency of the core crystal clock */
|
||||
if(CpuRegisters.Ecx != 0)
|
||||
{
|
||||
/* Save the base frequency for the APIC Timer */
|
||||
TimerCapabilities.TimerFrequency = CpuRegisters.Ecx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check RDTSCP instruction support if leaf supported */
|
||||
if(MaxExtendedLeaf >= CPUID_GET_EXTENDED_FEATURES)
|
||||
{
|
||||
CpuRegisters.Leaf = CPUID_GET_EXTENDED_FEATURES;
|
||||
CpuRegisters.SubLeaf = 0;
|
||||
CpuRegisters.Eax = 0;
|
||||
CpuRegisters.Ebx = 0;
|
||||
CpuRegisters.Ecx = 0;
|
||||
CpuRegisters.Edx = 0;
|
||||
AR::CpuFunc::CpuId(&CpuRegisters);
|
||||
|
||||
/* Verify RDTSCP support */
|
||||
if(CpuRegisters.Edx & CPUID_FEATURES_EDX_RDTSCP)
|
||||
{
|
||||
TimerCapabilities.RDTSCP = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check Invariant TSC if leaf supported */
|
||||
if(MaxExtendedLeaf >= CPUID_GET_ADVANCED_POWER_MANAGEMENT)
|
||||
{
|
||||
CpuRegisters.Leaf = CPUID_GET_ADVANCED_POWER_MANAGEMENT;
|
||||
CpuRegisters.SubLeaf = 0;
|
||||
CpuRegisters.Eax = 0;
|
||||
CpuRegisters.Ebx = 0;
|
||||
CpuRegisters.Ecx = 0;
|
||||
CpuRegisters.Edx = 0;
|
||||
AR::CpuFunc::CpuId(&CpuRegisters);
|
||||
|
||||
/* Verify Invariant TSC support */
|
||||
if(CpuRegisters.Edx & CPUID_FEATURES_EDX_TSCI)
|
||||
{
|
||||
TimerCapabilities.InvariantTsc = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the profile interrupt interval. The interval may be bounded by hardware capabilities.
|
||||
*
|
||||
|
||||
@@ -19,18 +19,20 @@ namespace HL
|
||||
{
|
||||
private:
|
||||
STATIC ULONG ProfilingInterval;
|
||||
STATIC TIMER_CAPABILITIES TimerCapabilities;
|
||||
STATIC ULONG TimerFrequency;
|
||||
|
||||
public:
|
||||
STATIC XTAPI VOID InitializeApicTimer(VOID);
|
||||
STATIC XTAPI VOID InitializeTimer(VOID);
|
||||
STATIC XTAPI ULONG_PTR SetProfileInterval(IN ULONG_PTR Interval);
|
||||
STATIC XTAPI VOID StartProfileInterrupt(IN KPROFILE_SOURCE ProfileSource);
|
||||
STATIC XTAPI VOID StopProfileInterrupt(IN KPROFILE_SOURCE ProfileSource);
|
||||
|
||||
private:
|
||||
STATIC XTAPI XTSTATUS CalibrateApicTimer();
|
||||
STATIC XTAPI XTSTATUS GetApicTimerFrequency(OUT PULONG Frequency);
|
||||
STATIC XTAPI VOID InitializeApicTimer(VOID);
|
||||
STATIC XTAPI VOID PitStallExecution(IN ULONG MicroSeconds);
|
||||
STATIC XTAPI VOID QueryTimerCapabilities(VOID);
|
||||
STATIC XTAPI VOID StallExecution(IN ULONG MicroSeconds);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user