From cec5e8b16bfa0fdf698526898773cf5194b61689 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Sun, 12 Apr 2026 23:58:48 +0200 Subject: [PATCH] Implement detection of timer capabilities --- sdk/xtdk/amd64/artypes.h | 51 ++++++-- sdk/xtdk/amd64/hltypes.h | 12 ++ sdk/xtdk/amd64/xtstruct.h | 3 + sdk/xtdk/i686/artypes.h | 51 ++++++-- sdk/xtdk/i686/hltypes.h | 13 ++ sdk/xtdk/i686/xtstruct.h | 3 + xtoskrnl/hl/data.cc | 3 + xtoskrnl/hl/x86/cpu.cc | 4 +- xtoskrnl/hl/x86/timer.cc | 238 +++++++++++++++++++++++----------- xtoskrnl/includes/hl/timer.hh | 6 +- 10 files changed, 289 insertions(+), 95 deletions(-) diff --git a/sdk/xtdk/amd64/artypes.h b/sdk/xtdk/amd64/artypes.h index 14d01ce..84908b5 100644 --- a/sdk/xtdk/amd64/artypes.h +++ b/sdk/xtdk/amd64/artypes.h @@ -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 */ diff --git a/sdk/xtdk/amd64/hltypes.h b/sdk/xtdk/amd64/hltypes.h index cbbe120..71f0381 100644 --- a/sdk/xtdk/amd64/hltypes.h +++ b/sdk/xtdk/amd64/hltypes.h @@ -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 */ diff --git a/sdk/xtdk/amd64/xtstruct.h b/sdk/xtdk/amd64/xtstruct.h index 2f80f93..5d1ea52 100644 --- a/sdk/xtdk/amd64/xtstruct.h +++ b/sdk/xtdk/amd64/xtstruct.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; diff --git a/sdk/xtdk/i686/artypes.h b/sdk/xtdk/i686/artypes.h index 7ef9f15..68c506c 100644 --- a/sdk/xtdk/i686/artypes.h +++ b/sdk/xtdk/i686/artypes.h @@ -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 */ diff --git a/sdk/xtdk/i686/hltypes.h b/sdk/xtdk/i686/hltypes.h index e0f3ccc..a6ee029 100644 --- a/sdk/xtdk/i686/hltypes.h +++ b/sdk/xtdk/i686/hltypes.h @@ -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 */ diff --git a/sdk/xtdk/i686/xtstruct.h b/sdk/xtdk/i686/xtstruct.h index 0c71625..0e6310b 100644 --- a/sdk/xtdk/i686/xtstruct.h +++ b/sdk/xtdk/i686/xtstruct.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; diff --git a/xtoskrnl/hl/data.cc b/xtoskrnl/hl/data.cc index 48099ee..7d5aae5 100644 --- a/xtoskrnl/hl/data.cc +++ b/xtoskrnl/hl/data.cc @@ -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; diff --git a/xtoskrnl/hl/x86/cpu.cc b/xtoskrnl/hl/x86/cpu.cc index b7730bb..253070c 100644 --- a/xtoskrnl/hl/x86/cpu.cc +++ b/xtoskrnl/hl/x86/cpu.cc @@ -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(); } diff --git a/xtoskrnl/hl/x86/timer.cc b/xtoskrnl/hl/x86/timer.cc index 7dd8e36..e19256e 100644 --- a/xtoskrnl/hl/x86/timer.cc +++ b/xtoskrnl/hl/x86/timer.cc @@ -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. * diff --git a/xtoskrnl/includes/hl/timer.hh b/xtoskrnl/includes/hl/timer.hh index 0b1a41d..a1f64f7 100644 --- a/xtoskrnl/includes/hl/timer.hh +++ b/xtoskrnl/includes/hl/timer.hh @@ -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); }; }