2 * FILE: hal/halx86/generic/timer.S
3 * COPYRIGHT: See COPYING in the top level directory
4 * PURPOSE: System Timer Interrupt and Management
5 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
8 /* INCLUDES ******************************************************************/
11 #include <internal/i386/asmmacro.S>
12 .intel_syntax noprefix
14 /* GLOBALS *******************************************************************/
16 _HalpLastPerfCounterLow: .long 0
17 _HalpLastPerfCounterHigh: .long 0
18 _HalpPerfCounterLow: .long 0
19 _HalpPerfCounterHigh: .long 0
22 .asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n"
24 /* FUNCTIONS *****************************************************************/
26 .globl _KeStallExecutionProcessor
27 .func KeStallExecutionProcessor
28 _KeStallExecutionProcessor:
30 /* Get the number of microseconds required */
33 /* Multiply by the stall factor */
34 mov eax, gs:[KPCR_STALL_SCALE_FACTOR]
37 /* Align to 16 bytes */
40 /* Jump to subtraction loop */
43 /* Align to 16 bytes */
46 /* Subtract one count */
56 .global _KeQueryPerformanceCounter
57 .func KeQueryPerformanceCounter
58 _KeQueryPerformanceCounter:
60 /* Check if we were called too early */
61 cmp dword ptr _HalpCurrentRollOver, 0
70 /* Disable interrupts */
76 /* Get the current value */
77 mov ebx, _HalpPerfCounterLow
78 mov esi, _HalpPerfCounterHigh
90 /* Enable interrupts and do a short wait */
95 /* Disable them again */
99 /* Get the counter value again */
100 mov eax, _HalpPerfCounterLow
101 mov edx, _HalpPerfCounterHigh
103 /* Check if someone updated the counter */
109 /* Check if the current 8254 value causes rollover */
111 add ecx, _HalpCurrentRollOver
116 /* Calculate the sum */
120 /* Check if we're above or below the last high value */
121 cmp edx, _HalpLastPerfCounterHigh
125 /* Check if we're above or below the last low value */
126 cmp eax, _HalpLastPerfCounterLow
131 /* Update the last value and bring back interrupts */
132 mov _HalpLastPerfCounterLow, eax
133 mov _HalpLastPerfCounterHigh, edx
136 /* Check if caller wants frequency */
137 cmp dword ptr [esp+12], 0
140 /* Save hard-coded frequency */
141 mov ecx, dword ptr [esp+12]
142 mov dword ptr [ecx], 1193182
143 mov dword ptr [ecx+4], 0
147 /* Restore volatiles */
154 /* Return empty, called too soon */
161 /* We might have an incoming interrupt, save EFLAGS and reset rollover */
163 mov ecx, _HalpCurrentRollOver
166 /* Check if interrupts were enabled and try again */
167 test esi, EFLAGS_INTERRUPT_MASK
170 /* They're not, continue where we left */
176 /* Get the last counter values */
177 mov ebx, _HalpLastPerfCounterLow
178 mov esi, _HalpLastPerfCounterHigh
180 /* Check if the previous value was 0 and go back if yes */
185 /* Make sure that the count is still valid */
189 cmp ebx, _HalpCurrentRollOver
192 /* Fixup the count with the last known value */
196 /* We might have an incoming interrupt, save EFLAGS */
200 /* Check if interrupts were enabled and try again */
201 test ecx, EFLAGS_INTERRUPT_MASK
204 /* They're not, continue where we left */
211 mov _HalpLastPerfCounterLow, eax
212 mov _HalpLastPerfCounterHigh, eax
216 .globl _HalpClockInterrupt
217 .func HalpClockInterrupt
218 //TRAP_FIXUPS hci_a, hci_t, DoFixupV86, DoFixupAbios
222 // INT_PROLOG hci_a, hci_t, DoPushFakeErrorCode
224 /* Push vector and make stack for IRQL */
228 /* Begin the interrupt */
232 // call _HalBeginSystemInterrupt
234 /* Check if it's spurious */
238 /* Update the performance counter */
240 mov eax, _HalpCurrentRollOver
241 add _HalpPerfCounterLow, eax
242 adc _HalpPerfCounterHigh, ebx
244 /* Get the time increment and check if someone changed the clock rate */
245 mov eax, _HalpCurrentTimeIncrement
246 cmp _HalpClockSetMSRate, ebx
247 jz _KeUpdateSystemTime
249 /* FIXME: Someone did! */
254 /* Exit the interrupt */
256 // jmp _Kei386EoiHelper