https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5ae27504672373728aa5a…
commit 5ae27504672373728aa5a0ba9b10b16ce9a4d900
Author: Ivan Labutin <linuxrf(a)gmail.com>
AuthorDate: Mon Nov 6 21:40:21 2017 +0300
Commit: Thomas Faber <thomas.faber(a)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