https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5ae27504672373728aa5a0...
commit 5ae27504672373728aa5a0ba9b10b16ce9a4d900 Author: Ivan Labutin linuxrf@gmail.com AuthorDate: Mon Nov 6 21:40:21 2017 +0300 Commit: Thomas Faber thomas.faber@reactos.org CommitDate: Thu Feb 15 12:45:29 2018 +0100
[HAL] Implement APIC-based profiling for x64. --- hal/halx86/apic/apic.h | 4 +++ hal/halx86/apic/apictimer.c | 79 +++++++++++++++++++++++++++++++++++++++--- hal/halx86/apic/halinit_apic.c | 3 ++ hal/halx86/include/halp.h | 4 +++ 4 files changed, 85 insertions(+), 5 deletions(-)
diff --git a/hal/halx86/apic/apic.h b/hal/halx86/apic/apic.h index 5de22834be..edabaa3b9d 100644 --- a/hal/halx86/apic/apic.h +++ b/hal/halx86/apic/apic.h @@ -278,5 +278,9 @@ VOID NTAPI ApicInitializeTimer(ULONG Cpu);
+VOID +NTAPI +HalInitializeProfiling(VOID); + VOID __cdecl ApicSpuriousService(VOID);
diff --git a/hal/halx86/apic/apictimer.c b/hal/halx86/apic/apictimer.c index cc0231623f..5fe9305660 100644 --- a/hal/halx86/apic/apictimer.c +++ b/hal/halx86/apic/apictimer.c @@ -16,6 +16,12 @@
extern LARGE_INTEGER HalpCpuClockFrequency;
+/* HAL profiling variables */ +BOOLEAN HalIsProfiling = FALSE; +ULONGLONG HalCurProfileInterval = 10000000; +ULONGLONG HalMinProfileInterval = 1000; +ULONGLONG HalMaxProfileInterval = 10000000; + /* TIMER FUNCTIONS ************************************************************/
VOID @@ -59,26 +65,89 @@ ApicInitializeTimer(ULONG Cpu)
/* PUBLIC FUNCTIONS ***********************************************************/
+VOID +NTAPI +HalInitializeProfiling(VOID) +{ + KeGetPcr()->HalReserved[HAL_PROFILING_INTERVAL] = HalCurProfileInterval; + KeGetPcr()->HalReserved[HAL_PROFILING_MULTIPLIER] = 1; /* TODO: HACK */ +} + VOID NTAPI HalStartProfileInterrupt(IN KPROFILE_SOURCE ProfileSource) { - UNIMPLEMENTED; - return; + LVT_REGISTER LvtEntry; + + /* Only handle ProfileTime */ + if (ProfileSource == ProfileTime) + { + /* OK, we are profiling now */ + HalIsProfiling = TRUE; + + /* Set interrupt interval */ + ApicWrite(APIC_TICR, KeGetPcr()->HalReserved[HAL_PROFILING_INTERVAL]); + + /* Unmask it */ + LvtEntry.Long = 0; + LvtEntry.TimerMode = 1; + LvtEntry.Vector = APIC_PROFILE_VECTOR; + LvtEntry.Mask = 0; + ApicWrite(APIC_TMRLVTR, LvtEntry.Long); + } }
VOID NTAPI HalStopProfileInterrupt(IN KPROFILE_SOURCE ProfileSource) { - UNIMPLEMENTED; - return; + LVT_REGISTER LvtEntry; + + /* Only handle ProfileTime */ + if (ProfileSource == ProfileTime) + { + /* We are not profiling */ + HalIsProfiling = FALSE; + + /* Mask interrupt */ + LvtEntry.Long = 0; + LvtEntry.TimerMode = 1; + LvtEntry.Vector = APIC_PROFILE_VECTOR; + LvtEntry.Mask = 1; + ApicWrite(APIC_TMRLVTR, LvtEntry.Long); + } }
ULONG_PTR NTAPI HalSetProfileInterval(IN ULONG_PTR Interval) { - UNIMPLEMENTED; + ULONGLONG TimerInterval; + ULONGLONG FixedInterval; + + FixedInterval = (ULONGLONG)Interval; + + /* Check bounds */ + if (FixedInterval < HalMinProfileInterval) + { + FixedInterval = HalMinProfileInterval; + } + else if (FixedInterval > HalMaxProfileInterval) + { + FixedInterval = HalMaxProfileInterval; + } + + /* Remember interval */ + HalCurProfileInterval = FixedInterval; + + /* Recalculate interval for APIC */ + TimerInterval = FixedInterval * KeGetPcr()->HalReserved[HAL_PROFILING_MULTIPLIER] / HalMaxProfileInterval; + + /* Remember recalculated interval in PCR */ + KeGetPcr()->HalReserved[HAL_PROFILING_INTERVAL] = (ULONG)TimerInterval; + + /* And set it */ + ApicWrite(APIC_TICR, (ULONG)TimerInterval); + return Interval; } diff --git a/hal/halx86/apic/halinit_apic.c b/hal/halx86/apic/halinit_apic.c index 0ac23c5c2f..cd5e0daf9d 100644 --- a/hal/halx86/apic/halinit_apic.c +++ b/hal/halx86/apic/halinit_apic.c @@ -32,6 +32,9 @@ HalpInitProcessor( /* Initialize the local APIC for this cpu */ ApicInitializeLocalApic(ProcessorNumber);
+ /* Initialize profiling data (but don't start it) */ + HalInitializeProfiling(); + /* Initialize the timer */ //ApicInitializeTimer(ProcessorNumber);
diff --git a/hal/halx86/include/halp.h b/hal/halx86/include/halp.h index 315282f809..079b1adb6d 100644 --- a/hal/halx86/include/halp.h +++ b/hal/halx86/include/halp.h @@ -49,6 +49,10 @@ VOID #define HAL_APC_REQUEST 0 #define HAL_DPC_REQUEST 1
+/* HAL profiling offsets in KeGetPcr()->HalReserved[] */ +#define HAL_PROFILING_INTERVAL 0 +#define HAL_PROFILING_MULTIPLIER 1 + /* CMOS Registers and Ports */ #define CMOS_CONTROL_PORT (PUCHAR)0x70 #define CMOS_DATA_PORT (PUCHAR)0x71