https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5ae27504672373728aa5a0ba9b10b16ce9a4d900

commit 5ae27504672373728aa5a0ba9b10b16ce9a4d900
Author:     Ivan Labutin <[email protected]>
AuthorDate: Mon Nov 6 21:40:21 2017 +0300
Commit:     Thomas Faber <[email protected]>
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

Reply via email to