1 /* 2 * PROJECT: ReactOS HAL 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: hal/halx86/apic/apictimer.c 5 * PURPOSE: System Profiling 6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include <hal.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 #include "apic.h" 16 17 extern LARGE_INTEGER HalpCpuClockFrequency; 18 19 /* HAL profiling variables */ 20 BOOLEAN HalIsProfiling = FALSE; 21 ULONGLONG HalCurProfileInterval = 10000000; 22 ULONGLONG HalMinProfileInterval = 1000; 23 ULONGLONG HalMaxProfileInterval = 10000000; 24 25 /* TIMER FUNCTIONS ************************************************************/ 26 27 VOID 28 NTAPI 29 ApicSetTimerInterval(ULONG MicroSeconds) 30 { 31 LVT_REGISTER LvtEntry; 32 ULONGLONG TimerInterval; 33 34 /* Calculate the Timer interval */ 35 TimerInterval = HalpCpuClockFrequency.QuadPart * MicroSeconds / 1000000; 36 37 /* Set the count interval */ 38 ApicWrite(APIC_TICR, (ULONG)TimerInterval); 39 40 /* Set to periodic */ 41 LvtEntry.Long = 0; 42 LvtEntry.TimerMode = 1; 43 LvtEntry.Vector = APIC_PROFILE_VECTOR; 44 LvtEntry.Mask = 0; 45 ApicWrite(APIC_TMRLVTR, LvtEntry.Long); 46 47 } 48 49 VOID 50 NTAPI 51 ApicInitializeTimer(ULONG Cpu) 52 { 53 54 /* Initialize the TSC */ 55 //HalpInitializeTsc(); 56 57 /* Set clock multiplier to 1 */ 58 ApicWrite(APIC_TDCR, TIMER_DV_DivideBy1); 59 60 ApicSetTimerInterval(1000); 61 62 // KeSetTimeIncrement 63 } 64 65 66 /* PUBLIC FUNCTIONS ***********************************************************/ 67 68 VOID 69 NTAPI 70 HalInitializeProfiling(VOID) 71 { 72 KeGetPcr()->HalReserved[HAL_PROFILING_INTERVAL] = HalCurProfileInterval; 73 KeGetPcr()->HalReserved[HAL_PROFILING_MULTIPLIER] = 1; /* TODO: HACK */ 74 } 75 76 VOID 77 NTAPI 78 HalStartProfileInterrupt(IN KPROFILE_SOURCE ProfileSource) 79 { 80 LVT_REGISTER LvtEntry; 81 82 /* Only handle ProfileTime */ 83 if (ProfileSource == ProfileTime) 84 { 85 /* OK, we are profiling now */ 86 HalIsProfiling = TRUE; 87 88 /* Set interrupt interval */ 89 ApicWrite(APIC_TICR, KeGetPcr()->HalReserved[HAL_PROFILING_INTERVAL]); 90 91 /* Unmask it */ 92 LvtEntry.Long = 0; 93 LvtEntry.TimerMode = 1; 94 LvtEntry.Vector = APIC_PROFILE_VECTOR; 95 LvtEntry.Mask = 0; 96 ApicWrite(APIC_TMRLVTR, LvtEntry.Long); 97 } 98 } 99 100 VOID 101 NTAPI 102 HalStopProfileInterrupt(IN KPROFILE_SOURCE ProfileSource) 103 { 104 LVT_REGISTER LvtEntry; 105 106 /* Only handle ProfileTime */ 107 if (ProfileSource == ProfileTime) 108 { 109 /* We are not profiling */ 110 HalIsProfiling = FALSE; 111 112 /* Mask interrupt */ 113 LvtEntry.Long = 0; 114 LvtEntry.TimerMode = 1; 115 LvtEntry.Vector = APIC_PROFILE_VECTOR; 116 LvtEntry.Mask = 1; 117 ApicWrite(APIC_TMRLVTR, LvtEntry.Long); 118 } 119 } 120 121 ULONG_PTR 122 NTAPI 123 HalSetProfileInterval(IN ULONG_PTR Interval) 124 { 125 ULONGLONG TimerInterval; 126 ULONGLONG FixedInterval; 127 128 FixedInterval = (ULONGLONG)Interval; 129 130 /* Check bounds */ 131 if (FixedInterval < HalMinProfileInterval) 132 { 133 FixedInterval = HalMinProfileInterval; 134 } 135 else if (FixedInterval > HalMaxProfileInterval) 136 { 137 FixedInterval = HalMaxProfileInterval; 138 } 139 140 /* Remember interval */ 141 HalCurProfileInterval = FixedInterval; 142 143 /* Recalculate interval for APIC */ 144 TimerInterval = FixedInterval * KeGetPcr()->HalReserved[HAL_PROFILING_MULTIPLIER] / HalMaxProfileInterval; 145 146 /* Remember recalculated interval in PCR */ 147 KeGetPcr()->HalReserved[HAL_PROFILING_INTERVAL] = (ULONG)TimerInterval; 148 149 /* And set it */ 150 ApicWrite(APIC_TICR, (ULONG)TimerInterval); 151 152 return Interval; 153 } 154