From: Ivan Labutin Date: Mon, 6 Nov 2017 18:40:21 +0000 (+0300) Subject: [HAL] Implement APIC-based profiling for x64. X-Git-Tag: 0.4.9-dev~15 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=5ae27504672373728aa5a0ba9b10b16ce9a4d900 [HAL] Implement APIC-based profiling for x64. --- diff --git a/hal/halx86/apic/apic.h b/hal/halx86/apic/apic.h index 5de22834be7..edabaa3b9db 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 cc0231623f2..5fe93056605 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 0ac23c5c2f5..cd5e0daf9d6 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 315282f8093..079b1adb6d7 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